CBMC
value_set_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 "value_set_dereference.h"
13 
14 #ifdef DEBUG
15 #include <iostream>
16 #endif
17 
18 #include <util/arith_tools.h>
19 #include <util/byte_operators.h>
20 #include <util/config.h>
21 #include <util/cprover_prefix.h>
22 #include <util/expr_iterator.h>
23 #include <util/expr_util.h>
24 #include <util/format_expr.h>
25 #include <util/fresh_symbol.h>
26 #include <util/json.h>
27 #include <util/message.h>
28 #include <util/pointer_expr.h>
31 #include <util/range.h>
32 #include <util/simplify_expr.h>
33 #include <util/symbol_table.h>
34 
35 #include <deque>
36 
37 #include "dereference_callback.h"
38 
49 static bool should_use_local_definition_for(const exprt &expr)
50 {
51  bool seen_symbol = false;
52  for(auto it = expr.depth_begin(), itend = expr.depth_end(); it != itend; ++it)
53  {
54  if(it->id() == ID_symbol)
55  {
56  if(seen_symbol)
57  return true;
58  else
59  seen_symbol = true;
60  }
61  }
62 
63  return false;
64 }
65 
67  const exprt &pointer,
68  const std::vector<exprt> &points_to_set,
69  const std::vector<exprt> &retained_values,
70  const exprt &value)
71 {
72  json_objectt json_result;
73  json_result["Pointer"] = json_stringt{format_to_string(pointer)};
74  json_result["PointsToSetSize"] =
75  json_numbert{std::to_string(points_to_set.size())};
76 
77  json_arrayt points_to_set_json;
78  for(const auto &object : points_to_set)
79  {
80  points_to_set_json.push_back(json_stringt{format_to_string(object)});
81  }
82 
83  json_result["PointsToSet"] = points_to_set_json;
84 
85  json_result["RetainedValuesSetSize"] =
86  json_numbert{std::to_string(points_to_set.size())};
87 
88  json_arrayt retained_values_set_json;
89  for(auto &retained_value : retained_values)
90  {
91  retained_values_set_json.push_back(
92  json_stringt{format_to_string(retained_value)});
93  }
94 
95  json_result["RetainedValuesSet"] = retained_values_set_json;
96 
97  json_result["Value"] = json_stringt{format_to_string(value)};
98 
99  return json_result;
100 }
101 
105 static optionalt<exprt>
106 try_add_offset_to_indices(const exprt &expr, const exprt &offset_elements)
107 {
108  if(const auto *index_expr = expr_try_dynamic_cast<index_exprt>(expr))
109  {
110  return index_exprt{
111  index_expr->array(),
112  plus_exprt{index_expr->index(),
114  offset_elements, index_expr->index().type())}};
115  }
116  else if(const auto *if_expr = expr_try_dynamic_cast<if_exprt>(expr))
117  {
118  const auto true_case =
119  try_add_offset_to_indices(if_expr->true_case(), offset_elements);
120  if(!true_case)
121  return {};
122  const auto false_case =
123  try_add_offset_to_indices(if_expr->false_case(), offset_elements);
124  if(!false_case)
125  return {};
126  return if_exprt{if_expr->cond(), *true_case, *false_case};
127  }
128  else if(can_cast_expr<typecast_exprt>(expr))
129  {
130  // the case of a type cast is _not_ handled here, because that would require
131  // doing arithmetic on the offset, and may result in an offset into some
132  // sub-element
133  return {};
134  }
135  else
136  {
137  return {};
138  }
139 }
140 
142  const exprt &pointer,
143  bool display_points_to_sets)
144 {
145  if(pointer.type().id()!=ID_pointer)
146  throw "dereference expected pointer type, but got "+
147  pointer.type().pretty();
148 
149  // we may get ifs due to recursive calls
150  if(pointer.id()==ID_if)
151  {
152  const if_exprt &if_expr=to_if_expr(pointer);
153  exprt true_case = dereference(if_expr.true_case(), display_points_to_sets);
154  exprt false_case =
155  dereference(if_expr.false_case(), display_points_to_sets);
156  return if_exprt(if_expr.cond(), true_case, false_case);
157  }
158  else if(pointer.id() == ID_typecast)
159  {
160  const exprt *underlying = &pointer;
161  // Note this isn't quite the same as skip_typecast, which would also skip
162  // things such as int-to-ptr typecasts which we shouldn't ignore
163  while(underlying->id() == ID_typecast &&
164  underlying->type().id() == ID_pointer)
165  {
166  underlying = &to_typecast_expr(*underlying).op();
167  }
168 
169  if(underlying->id() == ID_if && underlying->type().id() == ID_pointer)
170  {
171  const auto &if_expr = to_if_expr(*underlying);
172  return if_exprt(
173  if_expr.cond(),
174  dereference(
175  typecast_exprt(if_expr.true_case(), pointer.type()),
176  display_points_to_sets),
177  dereference(
178  typecast_exprt(if_expr.false_case(), pointer.type()),
179  display_points_to_sets));
180  }
181  }
182  else if(pointer.id() == ID_plus && pointer.operands().size() == 2)
183  {
184  // Try to improve results for *(p + i) where p points to known offsets but
185  // i is non-constant-- if `p` points to known positions in arrays or array-members
186  // of structs then we can add the non-constant expression `i` to the index
187  // instead of using a byte-extract expression.
188 
189  exprt pointer_expr = to_plus_expr(pointer).op0();
190  exprt offset_expr = to_plus_expr(pointer).op1();
191 
192  if(can_cast_type<pointer_typet>(offset_expr.type()))
193  std::swap(pointer_expr, offset_expr);
194 
195  if(
196  can_cast_type<pointer_typet>(pointer_expr.type()) &&
197  !can_cast_type<pointer_typet>(offset_expr.type()) &&
198  !can_cast_expr<constant_exprt>(offset_expr))
199  {
200  exprt derefd_pointer = dereference(pointer_expr);
201  if(
202  auto derefd_with_offset =
203  try_add_offset_to_indices(derefd_pointer, offset_expr))
204  return *derefd_with_offset;
205 
206  // If any of this fails, fall through to use the normal byte-extract path.
207  }
208  }
209 
210  return handle_dereference_base_case(pointer, display_points_to_sets);
211 }
212 
214  const exprt &pointer,
215  bool display_points_to_sets)
216 { // type of the object
217  const typet &type = to_pointer_type(pointer.type()).base_type();
218 
219  // collect objects the pointer may point to
220  const std::vector<exprt> points_to_set =
222 
223  // get the values of these
224  const std::vector<exprt> retained_values =
225  make_range(points_to_set).filter([&](const exprt &value) {
227  });
228 
229  exprt compare_against_pointer = pointer;
230 
231  if(retained_values.size() >= 2 && should_use_local_definition_for(pointer))
232  {
233  symbolt fresh_binder = get_fresh_aux_symbol(
234  pointer.type(),
235  "derefd_pointer",
236  "derefd_pointer",
240 
241  compare_against_pointer = fresh_binder.symbol_expr();
242  }
243 
244  auto values =
245  make_range(retained_values)
246  .map([&](const exprt &value) {
247  return build_reference_to(value, compare_against_pointer, ns);
248  })
249  .collect<std::deque<valuet>>();
250 
251  const bool may_fail =
252  values.empty() ||
253  std::any_of(values.begin(), values.end(), [](const valuet &value) {
254  return value.value.is_nil();
255  });
256 
257  if(may_fail)
258  {
259  values.push_front(get_failure_value(pointer, type));
260  }
261 
262  // now build big case split, but we only do "good" objects
263 
264  exprt result_value = nil_exprt{};
265 
266  for(const auto &value : values)
267  {
268  if(value.value.is_not_nil())
269  {
270  if(result_value.is_nil()) // first?
271  result_value = value.value;
272  else
273  result_value = if_exprt(value.pointer_guard, value.value, result_value);
274  }
275  }
276 
277  if(compare_against_pointer != pointer)
278  result_value =
279  let_exprt(to_symbol_expr(compare_against_pointer), pointer, result_value);
280 
281  if(display_points_to_sets)
282  {
284  pointer, points_to_set, retained_values, result_value);
285  }
286 
287  return result_value;
288 }
289 
291  const exprt &pointer,
292  const typet &type)
293 {
294  // first see if we have a "failed object" for this pointer
295  exprt failure_value;
296 
297  if(
298  const symbolt *failed_symbol =
300  {
301  // yes!
302  failure_value = failed_symbol->symbol_expr();
303  failure_value.set(ID_C_invalid_object, true);
304  }
305  else
306  {
307  // else: produce new symbol
308  symbolt &symbol = get_fresh_aux_symbol(
309  type,
310  "symex",
311  "invalid_object",
312  pointer.source_location(),
315 
316  // make it a lvalue, so we can assign to it
317  symbol.is_lvalue = true;
318 
319  failure_value = symbol.symbol_expr();
320  failure_value.set(ID_C_invalid_object, true);
321  }
322 
323  valuet result{};
324  result.value = failure_value;
325  result.pointer_guard = true_exprt();
326  return result;
327 }
328 
338  const typet &object_type,
339  const typet &dereference_type,
340  const namespacet &ns)
341 {
342  const typet *object_unwrapped = &object_type;
343  const typet *dereference_unwrapped = &dereference_type;
344  while(object_unwrapped->id() == ID_pointer &&
345  dereference_unwrapped->id() == ID_pointer)
346  {
347  object_unwrapped = &to_pointer_type(*object_unwrapped).base_type();
348  dereference_unwrapped =
349  &to_pointer_type(*dereference_unwrapped).base_type();
350  }
351  if(dereference_unwrapped->id() == ID_empty)
352  {
353  return true;
354  }
355  else if(dereference_unwrapped->id() == ID_pointer &&
356  object_unwrapped->id() != ID_pointer)
357  {
358 #ifdef DEBUG
359  std::cout << "value_set_dereference: the dereference type has "
360  "too many ID_pointer levels"
361  << std::endl;
362  std::cout << " object_type: " << object_type.pretty() << std::endl;
363  std::cout << " dereference_type: " << dereference_type.pretty()
364  << std::endl;
365 #endif
366  }
367 
368  if(object_type == dereference_type)
369  return true; // ok, they just match
370 
371  // check for struct prefixes
372 
373  const typet ot_base=ns.follow(object_type),
374  dt_base=ns.follow(dereference_type);
375 
376  if(ot_base.id()==ID_struct &&
377  dt_base.id()==ID_struct)
378  {
379  if(to_struct_type(dt_base).is_prefix_of(
380  to_struct_type(ot_base)))
381  return true; // ok, dt is a prefix of ot
382  }
383 
384  // we are generous about code pointers
385  if(dereference_type.id()==ID_code &&
386  object_type.id()==ID_code)
387  return true;
388 
389  // bitvectors of same width are ok
390  if((dereference_type.id()==ID_signedbv ||
391  dereference_type.id()==ID_unsignedbv) &&
392  (object_type.id()==ID_signedbv ||
393  object_type.id()==ID_unsignedbv) &&
394  to_bitvector_type(dereference_type).get_width()==
395  to_bitvector_type(object_type).get_width())
396  return true;
397 
398  // really different
399 
400  return false;
401 }
402 
417  const exprt &what,
418  bool exclude_null_derefs,
419  const irep_idt &language_mode)
420 {
421  if(what.id() == ID_unknown || what.id() == ID_invalid)
422  {
423  return false;
424  }
425 
427 
428  const exprt &root_object = o.root_object();
429  if(root_object.id() == ID_null_object)
430  {
431  return exclude_null_derefs;
432  }
433  else if(root_object.id() == ID_integer_address)
434  {
435  return language_mode == ID_java;
436  }
437 
438  return false;
439 }
440 
454  const exprt &what,
455  const exprt &pointer_expr,
456  const namespacet &ns)
457 {
458  const pointer_typet &pointer_type =
459  type_checked_cast<pointer_typet>(pointer_expr.type());
460  const typet &dereference_type = pointer_type.base_type();
461 
462  if(what.id()==ID_unknown ||
463  what.id()==ID_invalid)
464  {
465  return valuet();
466  }
467 
468  if(what.id()!=ID_object_descriptor)
469  throw "unknown points-to: "+what.id_string();
470 
472 
473  const exprt &root_object=o.root_object();
474  const exprt &object=o.object();
475 
476  #if 0
477  std::cout << "O: " << format(root_object) << '\n';
478  #endif
479 
480  valuet result;
481 
482  if(root_object.id() == ID_null_object)
483  {
484  if(o.offset().is_zero())
486  else
487  return valuet{};
488  }
489  else if(root_object.id()==ID_dynamic_object)
490  {
491  // constraint that it actually is a dynamic object
492  // this is also our guard
493  result.pointer_guard = is_dynamic_object_exprt(pointer_expr);
494 
495  // can't remove here, turn into *p
496  result.value = dereference_exprt{pointer_expr};
497  result.pointer = pointer_expr;
498  }
499  else if(root_object.id()==ID_integer_address)
500  {
501  // This is stuff like *((char *)5).
502  // This is turned into an access to __CPROVER_memory[...].
503 
504  const symbolt &memory_symbol=ns.lookup(CPROVER_PREFIX "memory");
505  const symbol_exprt symbol_expr(memory_symbol.name, memory_symbol.type);
506 
507  if(to_array_type(memory_symbol.type).element_type() == dereference_type)
508  {
509  // Types match already, what a coincidence!
510  // We can use an index expression.
511 
512  const index_exprt index_expr(
513  symbol_expr,
514  pointer_offset(pointer_expr),
515  to_array_type(memory_symbol.type).element_type());
516 
517  result.value=index_expr;
518  result.pointer = address_of_exprt{index_expr};
519  }
520  else if(dereference_type_compare(
521  to_array_type(memory_symbol.type).element_type(),
522  dereference_type,
523  ns))
524  {
525  const index_exprt index_expr(
526  symbol_expr,
527  pointer_offset(pointer_expr),
528  to_array_type(memory_symbol.type).element_type());
529  result.value=typecast_exprt(index_expr, dereference_type);
530  result.pointer =
532  }
533  else
534  {
535  // We need to use byte_extract.
536  // Won't do this without a commitment to an endianness.
537 
539  {
540  }
541  else
542  {
543  result.value = make_byte_extract(
544  symbol_expr, pointer_offset(pointer_expr), dereference_type);
545  result.pointer = address_of_exprt{result.value};
546  }
547  }
548  }
549  else
550  {
551  // something generic -- really has to be a symbol
552  address_of_exprt object_pointer(object);
553 
554  if(o.offset().is_zero())
555  {
556  result.pointer_guard = equal_exprt(
557  typecast_exprt::conditional_cast(pointer_expr, object_pointer.type()),
558  object_pointer);
559  }
560  else
561  {
562  result.pointer_guard=same_object(pointer_expr, object_pointer);
563  }
564 
565  const typet &object_type = object.type();
566  const typet &root_object_type = root_object.type();
567 
568  exprt root_object_subexpression=root_object;
569 
570  if(
571  dereference_type_compare(object_type, dereference_type, ns) &&
572  o.offset().is_zero())
573  {
574  // The simplest case: types match, and offset is zero!
575  // This is great, we are almost done.
576 
577  result.value = typecast_exprt::conditional_cast(object, dereference_type);
578  result.pointer =
580  }
581  else if(
582  root_object_type.id() == ID_array &&
584  to_array_type(root_object_type).element_type(), dereference_type, ns) &&
585  pointer_offset_bits(to_array_type(root_object_type).element_type(), ns) ==
586  pointer_offset_bits(dereference_type, ns))
587  {
588  // We have an array with a subtype that matches
589  // the dereferencing type.
590  exprt offset;
591 
592  // this should work as the object is essentially the root object
593  if(o.offset().is_constant())
594  offset=o.offset();
595  else
596  offset=pointer_offset(pointer_expr);
597 
598  // are we doing a byte?
599  auto element_size =
600  pointer_offset_size(to_array_type(root_object_type).element_type(), ns);
601 
602  if(!element_size.has_value() || *element_size == 0)
603  {
604  throw "unknown or invalid type size of:\n" +
605  to_array_type(root_object_type).element_type().pretty();
606  }
607 
608  exprt element_size_expr = from_integer(*element_size, offset.type());
609 
610  exprt adjusted_offset =
611  simplify_expr(div_exprt{offset, element_size_expr}, ns);
612 
613  index_exprt index_expr{root_object, adjusted_offset};
614  result.value =
615  typecast_exprt::conditional_cast(index_expr, dereference_type);
617  address_of_exprt{index_expr}, pointer_type);
618  }
619  else
620  {
621  // try to build a member/index expression - do not use byte_extract
622  auto subexpr = get_subexpression_at_offset(
623  root_object_subexpression, o.offset(), dereference_type, ns);
624  if(subexpr.has_value())
625  simplify(subexpr.value(), ns);
626  if(
627  subexpr.has_value() &&
628  subexpr.value().id() != ID_byte_extract_little_endian &&
629  subexpr.value().id() != ID_byte_extract_big_endian)
630  {
631  // Successfully found a member, array index, or combination thereof
632  // that matches the desired type and offset:
633  result.value = subexpr.value();
635  address_of_exprt{skip_typecast(subexpr.value())}, pointer_type);
636  return result;
637  }
638 
639  // we extract something from the root object
640  result.value=o.root_object();
643 
644  // this is relative to the root object
645  exprt offset;
646  if(o.offset().id()==ID_unknown)
647  offset=pointer_offset(pointer_expr);
648  else
649  offset=o.offset();
650 
651  if(memory_model(result.value, dereference_type, offset, ns))
652  {
653  // ok, done
654  }
655  else
656  {
657  return valuet(); // give up, no way that this is ok
658  }
659  }
660  }
661 
662  return result;
663 }
664 
665 static bool is_a_bv_type(const typet &type)
666 {
667  return type.id()==ID_unsignedbv ||
668  type.id()==ID_signedbv ||
669  type.id()==ID_bv ||
670  type.id()==ID_fixedbv ||
671  type.id()==ID_floatbv ||
672  type.id()==ID_c_enum_tag;
673 }
674 
684  exprt &value,
685  const typet &to_type,
686  const exprt &offset,
687  const namespacet &ns)
688 {
689  // we will allow more or less arbitrary pointer type cast
690 
691  const typet from_type=value.type();
692 
693  // first, check if it's really just a type coercion,
694  // i.e., both have exactly the same (constant) size,
695  // for bit-vector types or pointers
696 
697  if(
698  (is_a_bv_type(from_type) && is_a_bv_type(to_type)) ||
699  (from_type.id() == ID_pointer && to_type.id() == ID_pointer))
700  {
702  {
703  // avoid semantic conversion in case of
704  // cast to float or fixed-point,
705  // or cast from float or fixed-point
706 
707  if(
708  to_type.id() != ID_fixedbv && to_type.id() != ID_floatbv &&
709  from_type.id() != ID_fixedbv && from_type.id() != ID_floatbv)
710  {
711  value = typecast_exprt::conditional_cast(value, to_type);
712  return true;
713  }
714  }
715  }
716 
717  // otherwise, we will stitch it together from bytes
718 
719  return memory_model_bytes(value, to_type, offset, ns);
720 }
721 
731  exprt &value,
732  const typet &to_type,
733  const exprt &offset,
734  const namespacet &ns)
735 {
736  const typet from_type=value.type();
737 
738  // We simply refuse to convert to/from code.
739  if(from_type.id()==ID_code || to_type.id()==ID_code)
740  return false;
741 
742  // We won't do this without a commitment to an endianness.
744  return false;
745 
746  // But everything else we will try!
747  // We just rely on byte_extract to do the job!
748 
749  exprt result;
750 
751  // See if we have an array of bytes already,
752  // and we want something byte-sized.
753  auto from_type_element_type_size =
754  from_type.id() == ID_array
755  ? pointer_offset_size(to_array_type(from_type).element_type(), ns)
757 
758  auto to_type_size = pointer_offset_size(to_type, ns);
759 
760  if(
761  from_type.id() == ID_array && from_type_element_type_size.has_value() &&
762  *from_type_element_type_size == 1 && to_type_size.has_value() &&
763  *to_type_size == 1 &&
764  is_a_bv_type(to_array_type(from_type).element_type()) &&
765  is_a_bv_type(to_type))
766  {
767  // yes, can use 'index', but possibly need to convert
769  index_exprt(value, offset, to_array_type(from_type).element_type()),
770  to_type);
771  }
772  else
773  {
774  // no, use 'byte_extract'
775  result = make_byte_extract(value, offset, to_type);
776  }
777 
778  value=result;
779 
780  return true;
781 }
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
json_numbert
Definition: json.h:290
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
format
static format_containert< T > format(const T &o)
Definition: format.h:37
typecast_exprt::conditional_cast
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition: std_expr.h:2025
try_add_offset_to_indices
static optionalt< exprt > try_add_offset_to_indices(const exprt &expr, const exprt &offset_elements)
If expr is of the form (c1 ? e1[o1] : c2 ? e2[o2] : c3 ? ...) then return c1 ? e1[o1 + offset] : e2[o...
Definition: value_set_dereference.cpp:106
value_set_dereferencet::valuet
Return value for build_reference_to; see that method for documentation.
Definition: value_set_dereference.h:58
skip_typecast
const exprt & skip_typecast(const exprt &expr)
find the expression nested inside typecasts, if any
Definition: expr_util.cpp:217
exprt::depth_end
depth_iteratort depth_end()
Definition: expr.cpp:267
arith_tools.h
value_set_dereferencet::valuet::pointer_guard
exprt pointer_guard
Definition: value_set_dereference.h:63
to_struct_type
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition: std_types.h:308
value_set_dereferencet::memory_model
static bool memory_model(exprt &value, const typet &type, const exprt &offset, const namespacet &ns)
Replace value by an expression of type to_type corresponding to the value at memory address value + o...
Definition: value_set_dereference.cpp:683
value_set_dereferencet::ns
const namespacet & ns
Definition: value_set_dereference.h:99
typet
The type of an expression, extends irept.
Definition: type.h:28
fresh_symbol.h
irept::pretty
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
Definition: irep.cpp:495
messaget::status
mstreamt & status() const
Definition: message.h:414
to_if_expr
const if_exprt & to_if_expr(const exprt &expr)
Cast an exprt to an if_exprt.
Definition: std_expr.h:2403
value_set_dereference.h
symbolt::type
typet type
Type of symbol.
Definition: symbol.h:31
dereference_exprt
Operator to dereference a pointer.
Definition: pointer_expr.h:659
if_exprt
The trinary if-then-else operator.
Definition: std_expr.h:2322
is_dynamic_object_exprt
Evaluates to true if the operand is a pointer to a dynamic object.
Definition: pointer_expr.h:320
pointer_predicates.h
value_set_dereference_stats_to_json
static json_objectt value_set_dereference_stats_to_json(const exprt &pointer, const std::vector< exprt > &points_to_set, const std::vector< exprt > &retained_values, const exprt &value)
Definition: value_set_dereference.cpp:66
value_set_dereferencet::language_mode
const irep_idt language_mode
language_mode: ID_java, ID_C or another language identifier if we know the source language in use,...
Definition: value_set_dereference.h:104
object_descriptor_exprt
Split an expression into a base object and a (byte) offset.
Definition: pointer_expr.h:166
plus_exprt
The plus expression Associativity is not specified.
Definition: std_expr.h:946
value_set_dereferencet::should_ignore_value
static bool should_ignore_value(const exprt &what, bool exclude_null_derefs, const irep_idt &language_mode)
Determine whether possible alias what should be ignored when replacing a pointer by its referees.
Definition: value_set_dereference.cpp:416
value_set_dereferencet::exclude_null_derefs
const bool exclude_null_derefs
Flag indicating whether value_set_dereferencet::dereference should disregard an apparent attempt to d...
Definition: value_set_dereference.h:107
exprt
Base class for all expressions.
Definition: expr.h:55
value_set_dereferencet::get_failure_value
valuet get_failure_value(const exprt &pointer, const typet &type)
Definition: value_set_dereference.cpp:290
from_type
std::string from_type(const namespacet &ns, const irep_idt &identifier, const typet &type)
Definition: language_util.cpp:51
dereference_callbackt::get_or_create_failed_symbol
virtual const symbolt * get_or_create_failed_symbol(const exprt &expr)=0
to_string
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.
Definition: string_constraint.cpp:58
value_set_dereferencet::dereference_type_compare
static bool dereference_type_compare(const typet &object_type, const typet &dereference_type, const namespacet &ns)
Check if the two types have matching number of ID_pointer levels, with the dereference type eventuall...
Definition: value_set_dereference.cpp:337
configt::ansi_c
struct configt::ansi_ct ansi_c
to_bitvector_type
const bitvector_typet & to_bitvector_type(const typet &type)
Cast a typet to a bitvector_typet.
Definition: bitvector_types.h:32
div_exprt
Division.
Definition: std_expr.h:1096
symbol_exprt
Expression to hold a symbol (variable)
Definition: std_expr.h:112
dereference_callbackt::get_value_set
virtual std::vector< exprt > get_value_set(const exprt &expr) const =0
equal_exprt
Equality.
Definition: std_expr.h:1305
can_cast_type< pointer_typet >
bool can_cast_type< pointer_typet >(const typet &type)
Check whether a reference to a typet is a pointer_typet.
Definition: pointer_expr.h:66
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
json_arrayt
Definition: json.h:164
value_set_dereferencet::new_symbol_table
symbol_tablet & new_symbol_table
Definition: value_set_dereference.h:100
json_objectt
Definition: json.h:299
to_object_descriptor_expr
const object_descriptor_exprt & to_object_descriptor_expr(const exprt &expr)
Cast an exprt to an object_descriptor_exprt.
Definition: pointer_expr.h:238
namespacet
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:90
configt::ansi_ct::endiannesst::NO_ENDIANNESS
@ NO_ENDIANNESS
value_set_dereferencet::log
const messaget & log
Definition: value_set_dereference.h:108
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:84
namespacet::lookup
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Definition: namespace.cpp:138
irept::is_not_nil
bool is_not_nil() const
Definition: irep.h:380
byte_operators.h
Expression classes for byte-level operators.
null_pointer_exprt
The null pointer constant.
Definition: pointer_expr.h:734
value_set_dereferencet::valuet::pointer
exprt pointer
Definition: value_set_dereference.h:62
should_use_local_definition_for
static bool should_use_local_definition_for(const exprt &expr)
Returns true if expr is complicated enough that a local definition (using a let expression) is prefer...
Definition: value_set_dereference.cpp:49
irept::set
void set(const irep_idt &name, const irep_idt &value)
Definition: irep.h:420
multi_ary_exprt::op1
exprt & op1()
Definition: std_expr.h:883
nil_exprt
The NIL expression.
Definition: std_expr.h:3025
pointer_offset_bits
optionalt< mp_integer > pointer_offset_bits(const typet &type, const namespacet &ns)
Definition: pointer_offset_size.cpp:101
symbolt::symbol_expr
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
Definition: symbol.cpp:121
to_plus_expr
const plus_exprt & to_plus_expr(const exprt &expr)
Cast an exprt to a plus_exprt.
Definition: std_expr.h:986
value_set_dereferencet::dereference_callback
dereference_callbackt & dereference_callback
Definition: value_set_dereference.h:101
pointer_expr.h
irept::id_string
const std::string & id_string() const
Definition: irep.h:399
simplify
bool simplify(exprt &expr, const namespacet &ns)
Definition: simplify_expr.cpp:2926
to_pointer_type
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
Definition: pointer_expr.h:79
simplify_expr
exprt simplify_expr(exprt src, const namespacet &ns)
Definition: simplify_expr.cpp:2931
pointer_type
pointer_typet pointer_type(const typet &subtype)
Definition: c_types.cpp:253
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
format_to_string
std::string format_to_string(const T &o)
Definition: format.h:43
irept::is_nil
bool is_nil() const
Definition: irep.h:376
irept::id
const irep_idt & id() const
Definition: irep.h:396
range.h
value_set_dereferencet::memory_model_bytes
static bool memory_model_bytes(exprt &value, const typet &type, const exprt &offset, const namespacet &ns)
Replace value by an expression of type to_type corresponding to the value at memory address value + o...
Definition: value_set_dereference.cpp:730
unary_exprt::op
const exprt & op() const
Definition: std_expr.h:326
cprover_prefix.h
optionalt
nonstd::optional< T > optionalt
Definition: optional.h:35
pointer_offset
exprt pointer_offset(const exprt &pointer)
Definition: pointer_predicates.cpp:38
config
configt config
Definition: config.cpp:25
source_locationt
Definition: source_location.h:18
simplify_expr.h
exprt::is_zero
bool is_zero() const
Return whether the expression is a constant representing 0.
Definition: expr.cpp:65
expr_util.h
Deprecated expression utility functions.
format_expr.h
is_a_bv_type
static bool is_a_bv_type(const typet &type)
Definition: value_set_dereference.cpp:665
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
expr_iterator.h
if_exprt::true_case
exprt & true_case()
Definition: std_expr.h:2350
namespace_baset::follow
const typet & follow(const typet &) const
Resolve type symbol to the type it points to.
Definition: namespace.cpp:49
exprt::depth_begin
depth_iteratort depth_begin()
Definition: expr.cpp:265
symbolt
Symbol table entry.
Definition: symbol.h:27
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
get_subexpression_at_offset
optionalt< exprt > get_subexpression_at_offset(const exprt &expr, const mp_integer &offset_bytes, const typet &target_type_raw, const namespacet &ns)
Definition: pointer_offset_size.cpp:568
exprt::is_constant
bool is_constant() const
Return whether the expression is a constant.
Definition: expr.cpp:27
if_exprt::cond
exprt & cond()
Definition: std_expr.h:2340
dereference_callback.h
pointer_typet::base_type
const typet & base_type() const
The type of the data what we point to.
Definition: pointer_expr.h:35
CPROVER_PREFIX
#define CPROVER_PREFIX
Definition: cprover_prefix.h:14
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
json.h
value_set_dereferencet::build_reference_to
static valuet build_reference_to(const exprt &what, const exprt &pointer, const namespacet &ns)
Definition: value_set_dereference.cpp:453
config.h
can_cast_expr< typecast_exprt >
bool can_cast_expr< typecast_exprt >(const exprt &base)
Definition: std_expr.h:2035
can_cast_expr< constant_exprt >
bool can_cast_expr< constant_exprt >(const exprt &base)
Definition: std_expr.h:2976
exprt::operands
operandst & operands()
Definition: expr.h:94
symbolt::is_lvalue
bool is_lvalue
Definition: symbol.h:66
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
symbol_table.h
Author: Diffblue Ltd.
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
message.h
object_descriptor_exprt::object
exprt & object()
Definition: pointer_expr.h:193
true_exprt
The Boolean constant true.
Definition: std_expr.h:3007
multi_ary_exprt::op0
exprt & op0()
Definition: std_expr.h:877
exprt::source_location
const source_locationt & source_location() const
Definition: expr.h:211
make_range
ranget< iteratort > make_range(iteratort begin, iteratort end)
Definition: range.h:524
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
symbolt::name
irep_idt name
The unique identifier.
Definition: symbol.h:40
json_arrayt::push_back
jsont & push_back(const jsont &json)
Definition: json.h:212
let_exprt
A let expression.
Definition: std_expr.h:3141
configt::ansi_ct::endianness
endiannesst endianness
Definition: config.h:192
array_typet::element_type
const typet & element_type() const
The type of the elements of the array.
Definition: std_types.h:785
value_set_dereferencet::dereference
exprt dereference(const exprt &pointer, bool display_points_to_sets=false)
Dereference the given pointer-expression.
Definition: value_set_dereference.cpp:141
json_stringt
Definition: json.h:269
value_set_dereferencet::valuet::value
exprt value
Definition: value_set_dereference.h:61
object_descriptor_exprt::offset
exprt & offset()
Definition: pointer_expr.h:209
value_set_dereferencet::handle_dereference_base_case
exprt handle_dereference_base_case(const exprt &pointer, bool display_points_to_sets)
Definition: value_set_dereference.cpp:213