CBMC
goto_rw.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module:
4 
5 Author: Daniel Kroening
6 
7 Date: April 2010
8 
9 \*******************************************************************/
10 
11 #include "goto_rw.h"
12 
13 #include <memory>
14 
15 #include <util/arith_tools.h>
16 #include <util/bitvector_expr.h>
17 #include <util/byte_operators.h>
18 #include <util/endianness_map.h>
19 #include <util/expr_util.h>
20 #include <util/make_unique.h>
21 #include <util/pointer_expr.h>
23 #include <util/simplify_expr.h>
24 #include <util/std_code.h>
25 
26 #include <langapi/language_util.h>
27 
29 
31 
33 {
34 }
35 
36 void range_domaint::output(const namespacet &, std::ostream &out) const
37 {
38  out << "[";
39  for(const_iterator itr=begin();
40  itr!=end();
41  ++itr)
42  {
43  if(itr!=begin())
44  out << ";";
45  out << itr->first << ":" << itr->second;
46  }
47  out << "]";
48 }
49 
51 {
52  for(rw_range_sett::objectst::iterator it=r_range_set.begin();
53  it!=r_range_set.end();
54  ++it)
55  it->second=nullptr;
56 
57  for(rw_range_sett::objectst::iterator it=w_range_set.begin();
58  it!=w_range_set.end();
59  ++it)
60  it->second=nullptr;
61 }
62 
63 void rw_range_sett::output(std::ostream &out) const
64 {
65  out << "READ:\n";
66  for(const auto &read_object_entry : get_r_set())
67  {
68  out << " " << read_object_entry.first;
69  read_object_entry.second->output(ns, out);
70  out << '\n';
71  }
72 
73  out << '\n';
74 
75  out << "WRITE:\n";
76  for(const auto &written_object_entry : get_w_set())
77  {
78  out << " " << written_object_entry.first;
79  written_object_entry.second->output(ns, out);
80  out << '\n';
81  }
82 }
83 
85  get_modet mode,
86  const complex_real_exprt &expr,
87  const range_spect &range_start,
88  const range_spect &size)
89 {
90  get_objects_rec(mode, expr.op(), range_start, size);
91 }
92 
94  get_modet mode,
95  const complex_imag_exprt &expr,
96  const range_spect &range_start,
97  const range_spect &size)
98 {
99  const exprt &op = expr.op();
100 
101  auto subtype_bits =
103  CHECK_RETURN(subtype_bits.has_value());
104 
105  range_spect sub_size = range_spect::to_range_spect(*subtype_bits);
106  CHECK_RETURN(sub_size > range_spect{0});
107 
108  range_spect offset =
109  (range_start.is_unknown() || expr.id() == ID_complex_real) ? range_spect{0}
110  : sub_size;
111 
112  get_objects_rec(mode, op, range_start + offset, size);
113 }
114 
116  get_modet mode,
117  const if_exprt &if_expr,
118  const range_spect &range_start,
119  const range_spect &size)
120 {
121  if(if_expr.cond().is_false())
122  get_objects_rec(mode, if_expr.false_case(), range_start, size);
123  else if(if_expr.cond().is_true())
124  get_objects_rec(mode, if_expr.true_case(), range_start, size);
125  else
126  {
128 
129  get_objects_rec(mode, if_expr.false_case(), range_start, size);
130  get_objects_rec(mode, if_expr.true_case(), range_start, size);
131  }
132 }
133 
135  get_modet mode,
136  const dereference_exprt &deref,
137  const range_spect &,
138  const range_spect &)
139 {
140  const exprt &pointer=deref.pointer();
142  if(mode!=get_modet::READ)
143  get_objects_rec(mode, pointer);
144 }
145 
147  get_modet mode,
148  const byte_extract_exprt &be,
149  const range_spect &range_start,
150  const range_spect &size)
151 {
152  auto object_size_bits_opt = pointer_offset_bits(be.op().type(), ns);
153  const exprt simp_offset=simplify_expr(be.offset(), ns);
154 
155  auto index = numeric_cast<mp_integer>(simp_offset);
156  if(
157  range_start.is_unknown() || !index.has_value() ||
158  !object_size_bits_opt.has_value())
159  {
160  get_objects_rec(mode, be.op(), range_spect::unknown(), size);
161  }
162  else
163  {
164  *index *= 8;
165  if(*index >= *object_size_bits_opt)
166  return;
167 
168  endianness_mapt map(
169  be.op().type(),
170  be.id()==ID_byte_extract_little_endian,
171  ns);
172  range_spect offset = range_start;
173  if(*index > 0)
174  {
175  offset += range_spect::to_range_spect(
176  map.map_bit(numeric_cast_v<std::size_t>(*index)));
177  }
178  else
179  {
180  // outside the bounds of immediate byte-extract operand, might still be in
181  // bounds of a parent object
182  offset += range_spect::to_range_spect(*index);
183  }
184  get_objects_rec(mode, be.op(), offset, size);
185  }
186 }
187 
189  get_modet mode,
190  const shift_exprt &shift,
191  const range_spect &range_start,
192  const range_spect &size)
193 {
194  const exprt simp_distance=simplify_expr(shift.distance(), ns);
195 
196  auto op_bits = pointer_offset_bits(shift.op().type(), ns);
197 
198  range_spect src_size = op_bits.has_value()
199  ? range_spect::to_range_spect(*op_bits)
201 
202  const auto dist = numeric_cast<mp_integer>(simp_distance);
203  if(
204  range_start.is_unknown() || size.is_unknown() || src_size.is_unknown() ||
205  !dist.has_value())
206  {
208  mode, shift.op(), range_spect::unknown(), range_spect::unknown());
211  }
212  else
213  {
214  const range_spect dist_r = range_spect::to_range_spect(*dist);
215 
216  // not sure whether to worry about
217  // config.ansi_c.endianness==configt::ansi_ct::IS_LITTLE_ENDIAN
218  // right here maybe?
219 
220  if(shift.id()==ID_ashr || shift.id()==ID_lshr)
221  {
222  range_spect sh_range_start=range_start;
223  sh_range_start+=dist_r;
224 
225  range_spect sh_size=std::min(size, src_size-sh_range_start);
226 
227  if(sh_range_start >= range_spect{0} && sh_range_start < src_size)
228  get_objects_rec(mode, shift.op(), sh_range_start, sh_size);
229  }
230  if(src_size >= dist_r)
231  {
232  range_spect sh_size=std::min(size, src_size-dist_r);
233 
234  get_objects_rec(mode, shift.op(), range_start, sh_size);
235  }
236  }
237 }
238 
240  get_modet mode,
241  const member_exprt &expr,
242  const range_spect &range_start,
243  const range_spect &size)
244 {
245  const typet &type = expr.struct_op().type();
246 
247  if(
248  type.id() == ID_union || type.id() == ID_union_tag ||
249  range_start.is_unknown())
250  {
251  get_objects_rec(mode, expr.struct_op(), range_start, size);
252  return;
253  }
254 
255  const struct_typet &struct_type = to_struct_type(ns.follow(type));
256 
257  auto offset_bits =
258  member_offset_bits(struct_type, expr.get_component_name(), ns);
259 
261 
262  if(offset_bits.has_value())
263  {
264  offset = range_spect::to_range_spect(*offset_bits);
265  offset += range_start;
266  }
267 
268  get_objects_rec(mode, expr.struct_op(), offset, size);
269 }
270 
272  get_modet mode,
273  const index_exprt &expr,
274  const range_spect &range_start,
275  const range_spect &size)
276 {
277  if(expr.array().id() == ID_null_object)
278  return;
279 
280  range_spect sub_size = range_spect::unknown();
281  const typet &type = expr.array().type();
282 
283  if(type.id()==ID_vector)
284  {
285  const vector_typet &vector_type=to_vector_type(type);
286 
287  auto subtype_bits = pointer_offset_bits(vector_type.element_type(), ns);
288 
289  if(subtype_bits.has_value())
290  sub_size = range_spect::to_range_spect(*subtype_bits);
291  }
292  else if(type.id()==ID_array)
293  {
294  const array_typet &array_type=to_array_type(type);
295 
296  auto subtype_bits = pointer_offset_bits(array_type.element_type(), ns);
297 
298  if(subtype_bits.has_value())
299  sub_size = range_spect::to_range_spect(*subtype_bits);
300  }
301  else
302  return;
303 
304  const exprt simp_index=simplify_expr(expr.index(), ns);
305 
306  const auto index = numeric_cast<mp_integer>(simp_index);
307  if(!index.has_value())
309 
310  if(range_start.is_unknown() || sub_size.is_unknown() || !index.has_value())
311  get_objects_rec(mode, expr.array(), range_spect::unknown(), size);
312  else
313  {
315  mode,
316  expr.array(),
317  range_start + range_spect::to_range_spect(*index) * sub_size,
318  size);
319  }
320 }
321 
323  get_modet mode,
324  const array_exprt &expr,
325  const range_spect &range_start,
326  const range_spect &size)
327 {
328  const array_typet &array_type = expr.type();
329 
330  auto subtype_bits = pointer_offset_bits(array_type.element_type(), ns);
331 
332  if(!subtype_bits.has_value())
333  {
334  forall_operands(it, expr)
336 
337  return;
338  }
339 
340  range_spect sub_size = range_spect::to_range_spect(*subtype_bits);
341 
342  range_spect offset{0};
343  range_spect full_r_s =
344  range_start.is_unknown() ? range_spect{0} : range_start;
345  range_spect full_r_e =
346  size.is_unknown()
347  ? sub_size * range_spect::to_range_spect(expr.operands().size())
348  : full_r_s + size;
349 
350  forall_operands(it, expr)
351  {
352  if(full_r_s<=offset+sub_size && full_r_e>offset)
353  {
354  range_spect cur_r_s =
355  full_r_s <= offset ? range_spect{0} : full_r_s - offset;
356  range_spect cur_r_e=
357  full_r_e>offset+sub_size ? sub_size : full_r_e-offset;
358 
359  get_objects_rec(mode, *it, cur_r_s, cur_r_e-cur_r_s);
360  }
361 
362  offset+=sub_size;
363  }
364 }
365 
367  get_modet mode,
368  const struct_exprt &expr,
369  const range_spect &range_start,
370  const range_spect &size)
371 {
372  const struct_typet &struct_type=
373  to_struct_type(ns.follow(expr.type()));
374 
375  auto struct_bits = pointer_offset_bits(struct_type, ns);
376 
377  range_spect full_size = struct_bits.has_value()
378  ? range_spect::to_range_spect(*struct_bits)
380 
381  range_spect offset = range_spect{0};
382  range_spect full_r_s =
383  range_start.is_unknown() ? range_spect{0} : range_start;
384  range_spect full_r_e = size.is_unknown() || full_size.is_unknown()
386  : full_r_s + size;
387 
388  forall_operands(it, expr)
389  {
390  auto it_bits = pointer_offset_bits(it->type(), ns);
391 
392  range_spect sub_size = it_bits.has_value()
393  ? range_spect::to_range_spect(*it_bits)
395 
396  if(offset.is_unknown())
397  {
398  get_objects_rec(mode, *it, range_spect{0}, sub_size);
399  }
400  else if(sub_size.is_unknown())
401  {
402  if(full_r_e.is_unknown() || full_r_e > offset)
403  {
404  range_spect cur_r_s =
405  full_r_s <= offset ? range_spect{0} : full_r_s - offset;
406 
407  get_objects_rec(mode, *it, cur_r_s, range_spect::unknown());
408  }
409 
410  offset = range_spect::unknown();
411  }
412  else if(full_r_e.is_unknown())
413  {
414  if(full_r_s<=offset+sub_size)
415  {
416  range_spect cur_r_s =
417  full_r_s <= offset ? range_spect{0} : full_r_s - offset;
418 
419  get_objects_rec(mode, *it, cur_r_s, sub_size-cur_r_s);
420  }
421 
422  offset+=sub_size;
423  }
424  else if(full_r_s<=offset+sub_size && full_r_e>offset)
425  {
426  range_spect cur_r_s =
427  full_r_s <= offset ? range_spect{0} : full_r_s - offset;
428  range_spect cur_r_e=
429  full_r_e>offset+sub_size ? sub_size : full_r_e-offset;
430 
431  get_objects_rec(mode, *it, cur_r_s, cur_r_e-cur_r_s);
432 
433  offset+=sub_size;
434  }
435  }
436 }
437 
439  get_modet mode,
440  const typecast_exprt &tc,
441  const range_spect &range_start,
442  const range_spect &size)
443 {
444  const exprt &op=tc.op();
445 
446  auto op_bits = pointer_offset_bits(op.type(), ns);
447 
448  range_spect new_size = op_bits.has_value()
449  ? range_spect::to_range_spect(*op_bits)
451 
452  if(range_start.is_unknown())
453  new_size = range_spect::unknown();
454  else if(!new_size.is_unknown())
455  {
456  if(new_size<=range_start)
457  return;
458 
459  new_size-=range_start;
460  new_size=std::min(size, new_size);
461  }
462 
463  get_objects_rec(mode, op, range_start, new_size);
464 }
465 
467 {
468  if(
469  object.id() == ID_string_constant || object.id() == ID_label ||
470  object.id() == ID_array || object.id() == ID_null_object ||
471  object.id() == ID_symbol)
472  {
473  // constant, nothing to do
474  return;
475  }
476  else if(object.id()==ID_dereference)
477  {
479  }
480  else if(object.id()==ID_index)
481  {
482  const index_exprt &index=to_index_expr(object);
483 
486  }
487  else if(object.id()==ID_member)
488  {
489  const member_exprt &member=to_member_expr(object);
490 
492  }
493  else if(object.id()==ID_if)
494  {
495  const if_exprt &if_expr=to_if_expr(object);
496 
500  }
501  else if(object.id()==ID_byte_extract_little_endian ||
502  object.id()==ID_byte_extract_big_endian)
503  {
504  const byte_extract_exprt &be=to_byte_extract_expr(object);
505 
507  }
508  else if(object.id()==ID_typecast)
509  {
510  const typecast_exprt &tc=to_typecast_expr(object);
511 
513  }
514  else
515  throw "rw_range_sett: address_of '" + object.id_string() + "' not handled";
516 }
517 
519  get_modet mode,
520  const irep_idt &identifier,
521  const range_spect &range_start,
522  const range_spect &range_end)
523 {
524  objectst::iterator entry=
526  .insert(
527  std::pair<const irep_idt &, std::unique_ptr<range_domain_baset>>(
528  identifier, nullptr))
529  .first;
530 
531  if(entry->second==nullptr)
532  entry->second=util_make_unique<range_domaint>();
533 
534  static_cast<range_domaint&>(*entry->second).push_back(
535  {range_start, range_end});
536 }
537 
539  get_modet mode,
540  const exprt &expr,
541  const range_spect &range_start,
542  const range_spect &size)
543 {
544  if(expr.id() == ID_complex_real)
546  mode, to_complex_real_expr(expr), range_start, size);
547  else if(expr.id() == ID_complex_imag)
549  mode, to_complex_imag_expr(expr), range_start, size);
550  else if(expr.id()==ID_typecast)
552  mode,
553  to_typecast_expr(expr),
554  range_start,
555  size);
556  else if(expr.id()==ID_if)
557  get_objects_if(mode, to_if_expr(expr), range_start, size);
558  else if(expr.id()==ID_dereference)
560  mode,
561  to_dereference_expr(expr),
562  range_start,
563  size);
564  else if(expr.id()==ID_byte_extract_little_endian ||
565  expr.id()==ID_byte_extract_big_endian)
567  mode,
568  to_byte_extract_expr(expr),
569  range_start,
570  size);
571  else if(expr.id()==ID_shl ||
572  expr.id()==ID_ashr ||
573  expr.id()==ID_lshr)
574  get_objects_shift(mode, to_shift_expr(expr), range_start, size);
575  else if(expr.id()==ID_member)
576  get_objects_member(mode, to_member_expr(expr), range_start, size);
577  else if(expr.id()==ID_index)
578  get_objects_index(mode, to_index_expr(expr), range_start, size);
579  else if(expr.id()==ID_array)
580  get_objects_array(mode, to_array_expr(expr), range_start, size);
581  else if(expr.id()==ID_struct)
582  get_objects_struct(mode, to_struct_expr(expr), range_start, size);
583  else if(expr.id()==ID_symbol)
584  {
585  const symbol_exprt &symbol=to_symbol_expr(expr);
586  const irep_idt identifier=symbol.get_identifier();
587 
588  auto symbol_bits = pointer_offset_bits(symbol.type(), ns);
589 
590  range_spect full_size = symbol_bits.has_value()
591  ? range_spect::to_range_spect(*symbol_bits)
593 
594  if(
595  !full_size.is_unknown() &&
596  (full_size == range_spect{0} ||
597  (full_size > range_spect{0} && !range_start.is_unknown() &&
598  range_start >= full_size)))
599  {
600  // nothing to do, these are effectively constants (like function
601  // symbols or structs with no members)
602  // OR: invalid memory accesses
603  }
604  else if(!range_start.is_unknown() && range_start >= range_spect{0})
605  {
606  range_spect range_end =
607  size.is_unknown() ? range_spect::unknown() : range_start + size;
608  if(!size.is_unknown() && !full_size.is_unknown())
609  range_end=std::min(range_end, full_size);
610 
611  add(mode, identifier, range_start, range_end);
612  }
613  else
614  add(mode, identifier, range_spect{0}, range_spect::unknown());
615  }
616  else if(mode==get_modet::READ && expr.id()==ID_address_of)
618  else if(mode==get_modet::READ)
619  {
620  // possibly affects the full object size, even if range_start/size
621  // are only a subset of the bytes (e.g., when using the result of
622  // arithmetic operations)
623  forall_operands(it, expr)
624  get_objects_rec(mode, *it);
625  }
626  else if(expr.id() == ID_null_object ||
627  expr.id() == ID_string_constant)
628  {
629  // dereferencing may yield some weird ones, ignore these
630  }
631  else if(mode==get_modet::LHS_W)
632  {
633  forall_operands(it, expr)
634  get_objects_rec(mode, *it);
635  }
636  else
637  throw "rw_range_sett: assignment to '" + expr.id_string() + "' not handled";
638 }
639 
641 {
642  auto expr_bits = pointer_offset_bits(expr.type(), ns);
643 
644  range_spect size = expr_bits.has_value()
645  ? range_spect::to_range_spect(*expr_bits)
647 
648  get_objects_rec(mode, expr, range_spect{0}, size);
649 }
650 
652 {
653  // TODO should recurse into various composite types
654  if(type.id()==ID_array)
655  {
656  const auto &array_type = to_array_type(type);
657  get_objects_rec(array_type.element_type());
658  get_objects_rec(get_modet::READ, array_type.size());
659  }
660 }
661 
663  const irep_idt &,
665  get_modet mode,
666  const exprt &pointer)
667 {
669  ode.build(dereference_exprt{skip_typecast(pointer)}, ns);
672 }
673 
675  get_modet mode,
676  const dereference_exprt &deref,
677  const range_spect &range_start,
678  const range_spect &size)
679 {
681  mode,
682  deref,
683  range_start,
684  size);
685 
686  exprt object=deref;
687  dereference(function, target, object, ns, value_sets);
688 
689  auto type_bits = pointer_offset_bits(object.type(), ns);
690 
691  range_spect new_size = range_spect::unknown();
692 
693  if(type_bits.has_value())
694  {
695  new_size = range_spect::to_range_spect(*type_bits);
696 
697  if(range_start.is_unknown() || new_size <= range_start)
698  new_size = range_spect::unknown();
699  else
700  {
701  new_size -= range_start;
702  new_size = std::min(size, new_size);
703  }
704  }
705 
706  // value_set_dereferencet::build_reference_to will turn *p into
707  // DYNAMIC_OBJECT(p) ? *p : invalid_objectN
708  if(object.is_not_nil() && !has_subexpr(object, ID_dereference))
709  get_objects_rec(mode, object, range_start, new_size);
710 }
711 
713  const namespacet &ns, std::ostream &out) const
714 {
715  out << "[";
716  for(const_iterator itr=begin();
717  itr!=end();
718  ++itr)
719  {
720  if(itr!=begin())
721  out << ";";
722  out << itr->first << ":" << itr->second.first;
723  // we don't know what mode (language) we are in, so we rely on the default
724  // language to be reasonable for from_expr
725  out << " if " << from_expr(ns, irep_idt(), itr->second.second);
726  }
727  out << "]";
728 }
729 
731  get_modet mode,
732  const if_exprt &if_expr,
733  const range_spect &range_start,
734  const range_spect &size)
735 {
736  if(if_expr.cond().is_false())
737  get_objects_rec(mode, if_expr.false_case(), range_start, size);
738  else if(if_expr.cond().is_true())
739  get_objects_rec(mode, if_expr.true_case(), range_start, size);
740  else
741  {
743 
744  guardt copy = guard;
745 
746  guard.add(not_exprt(if_expr.cond()));
747  get_objects_rec(mode, if_expr.false_case(), range_start, size);
748  guard = copy;
749 
750  guard.add(if_expr.cond());
751  get_objects_rec(mode, if_expr.true_case(), range_start, size);
752  guard = std::move(copy);
753  }
754 }
755 
757  get_modet mode,
758  const irep_idt &identifier,
759  const range_spect &range_start,
760  const range_spect &range_end)
761 {
762  objectst::iterator entry=
764  .insert(
765  std::pair<const irep_idt &, std::unique_ptr<range_domain_baset>>(
766  identifier, nullptr))
767  .first;
768 
769  if(entry->second==nullptr)
770  entry->second=util_make_unique<guarded_range_domaint>();
771 
772  static_cast<guarded_range_domaint&>(*entry->second).insert(
773  {range_start, {range_end, guard.as_expr()}});
774 }
775 
776 static void goto_rw_assign(
777  const irep_idt &function,
779  const exprt &lhs,
780  const exprt &rhs,
781  rw_range_sett &rw_set)
782 {
783  rw_set.get_objects_rec(
784  function, target, rw_range_sett::get_modet::LHS_W, lhs);
785  rw_set.get_objects_rec(function, target, rw_range_sett::get_modet::READ, rhs);
786 }
787 
788 static void goto_rw_other(
789  const irep_idt &function,
791  const codet &code,
792  rw_range_sett &rw_set)
793 {
794  const irep_idt &statement = code.get_statement();
795 
796  if(statement == ID_printf)
797  {
798  // if it's printf, mark the operands as read here
799  for(const auto &op : code.operands())
800  {
801  rw_set.get_objects_rec(
802  function, target, rw_range_sett::get_modet::READ, op);
803  }
804  }
805  else if(statement == ID_array_equal)
806  {
807  // mark the dereferenced operands as being read
808  PRECONDITION(code.operands().size() == 3);
809  rw_set.get_array_objects(
810  function, target, rw_range_sett::get_modet::READ, code.op0());
811  rw_set.get_array_objects(
812  function, target, rw_range_sett::get_modet::READ, code.op1());
813  // the third operand is the result
814  rw_set.get_objects_rec(
815  function, target, rw_range_sett::get_modet::LHS_W, code.op2());
816  }
817  else if(statement == ID_array_set)
818  {
819  PRECONDITION(code.operands().size() == 2);
820  rw_set.get_array_objects(
821  function, target, rw_range_sett::get_modet::LHS_W, code.op0());
822  rw_set.get_objects_rec(
823  function, target, rw_range_sett::get_modet::READ, code.op1());
824  }
825  else if(statement == ID_array_copy || statement == ID_array_replace)
826  {
827  PRECONDITION(code.operands().size() == 2);
828  rw_set.get_array_objects(
829  function, target, rw_range_sett::get_modet::LHS_W, code.op0());
830  rw_set.get_array_objects(
831  function, target, rw_range_sett::get_modet::READ, code.op1());
832  }
833  else if(statement == ID_havoc_object)
834  {
835  PRECONDITION(code.operands().size() == 1);
836  // re-use get_array_objects as this havoc_object affects whatever is the
837  // object being the pointer that code.op0() is
838  rw_set.get_array_objects(
839  function, target, rw_range_sett::get_modet::LHS_W, code.op0());
840  }
841 }
842 
843 static void goto_rw(
844  const irep_idt &function,
846  const exprt &lhs,
847  const exprt &function_expr,
848  const exprt::operandst &arguments,
849  rw_range_sett &rw_set)
850 {
851  if(lhs.is_not_nil())
852  rw_set.get_objects_rec(
853  function, target, rw_range_sett::get_modet::LHS_W, lhs);
854 
855  rw_set.get_objects_rec(
856  function, target, rw_range_sett::get_modet::READ, function_expr);
857 
858  for(const auto &argument : arguments)
859  {
860  rw_set.get_objects_rec(
861  function, target, rw_range_sett::get_modet::READ, argument);
862  }
863 }
864 
865 void goto_rw(
866  const irep_idt &function,
868  rw_range_sett &rw_set)
869 {
870  switch(target->type())
871  {
872  case NO_INSTRUCTION_TYPE:
873  case INCOMPLETE_GOTO:
874  UNREACHABLE;
875  break;
876 
877  case GOTO:
878  case ASSUME:
879  case ASSERT:
880  rw_set.get_objects_rec(
881  function, target, rw_range_sett::get_modet::READ, target->condition());
882  break;
883 
884  case SET_RETURN_VALUE:
885  rw_set.get_objects_rec(
886  function, target, rw_range_sett::get_modet::READ, target->return_value());
887  break;
888 
889  case OTHER:
890  goto_rw_other(function, target, target->get_other(), rw_set);
891  break;
892 
893  case SKIP:
894  case START_THREAD:
895  case END_THREAD:
896  case LOCATION:
897  case END_FUNCTION:
898  case ATOMIC_BEGIN:
899  case ATOMIC_END:
900  case THROW:
901  case CATCH:
902  // these don't read or write anything
903  break;
904 
905  case ASSIGN:
907  function, target, target->assign_lhs(), target->assign_rhs(), rw_set);
908  break;
909 
910  case DEAD:
911  rw_set.get_objects_rec(
912  function, target, rw_range_sett::get_modet::LHS_W, target->dead_symbol());
913  break;
914 
915  case DECL:
916  rw_set.get_objects_rec(function, target, target->decl_symbol().type());
917  rw_set.get_objects_rec(
918  function, target, rw_range_sett::get_modet::LHS_W, target->decl_symbol());
919  break;
920 
921  case FUNCTION_CALL:
922  goto_rw(
923  function,
924  target,
925  target->call_lhs(),
926  target->call_function(),
927  target->call_arguments(),
928  rw_set);
929  break;
930  }
931 }
932 
933 void goto_rw(
934  const irep_idt &function,
935  const goto_programt &goto_program,
936  rw_range_sett &rw_set)
937 {
938  forall_goto_program_instructions(i_it, goto_program)
939  goto_rw(function, i_it, rw_set);
940 }
941 
942 void goto_rw(const goto_functionst &goto_functions,
943  const irep_idt &function,
944  rw_range_sett &rw_set)
945 {
946  goto_functionst::function_mapt::const_iterator f_it=
947  goto_functions.function_map.find(function);
948 
949  if(f_it!=goto_functions.function_map.end())
950  {
951  const goto_programt &body=f_it->second.body;
952 
953  goto_rw(f_it->first, body, rw_set);
954  }
955 }
guard_exprt
Definition: guard_expr.h:23
UNREACHABLE
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:503
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
rw_range_sett::get_r_set
const objectst & get_r_set() const
Definition: goto_rw.h:220
rw_range_sett::get_objects_if
virtual void get_objects_if(get_modet mode, const if_exprt &if_expr, const range_spect &range_start, const range_spect &size)
Definition: goto_rw.cpp:115
rw_range_sett::get_objects_shift
virtual void get_objects_shift(get_modet mode, const shift_exprt &shift, const range_spect &range_start, const range_spect &size)
Definition: goto_rw.cpp:188
skip_typecast
const exprt & skip_typecast(const exprt &expr)
find the expression nested inside typecasts, if any
Definition: expr_util.cpp:217
has_subexpr
bool has_subexpr(const exprt &expr, const std::function< bool(const exprt &)> &pred)
returns true if the expression has a subexpression that satisfies pred
Definition: expr_util.cpp:139
SET_RETURN_VALUE
@ SET_RETURN_VALUE
Definition: goto_program.h:45
guarded_range_domaint::const_iterator
sub_typet::const_iterator const_iterator
Definition: goto_rw.h:439
arith_tools.h
rw_range_sett::get_objects_address_of
virtual void get_objects_address_of(const exprt &object)
Definition: goto_rw.cpp:466
rw_range_sett::get_objects_array
virtual void get_objects_array(get_modet mode, const array_exprt &expr, const range_spect &range_start, const range_spect &size)
Definition: goto_rw.cpp:322
to_array_expr
const array_exprt & to_array_expr(const exprt &expr)
Cast an exprt to an array_exprt.
Definition: std_expr.h:1603
codet::op0
exprt & op0()
Definition: expr.h:125
object_descriptor_exprt::build
void build(const exprt &expr, const namespacet &ns)
Given an expression expr, attempt to find the underlying object it represents by skipping over type c...
Definition: pointer_expr.cpp:107
to_struct_type
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition: std_types.h:308
address_of_exprt::object
exprt & object()
Definition: pointer_expr.h:380
range_spect::is_unknown
bool is_unknown() const
Definition: goto_rw.h:74
rw_range_sett::get_array_objects
virtual void get_array_objects(const irep_idt &, goto_programt::const_targett, get_modet, const exprt &)
Definition: goto_rw.cpp:662
rw_range_sett::get_objects_byte_extract
virtual void get_objects_byte_extract(get_modet mode, const byte_extract_exprt &be, const range_spect &range_start, const range_spect &size)
Definition: goto_rw.cpp:146
to_dereference_expr
const dereference_exprt & to_dereference_expr(const exprt &expr)
Cast an exprt to a dereference_exprt.
Definition: pointer_expr.h:716
CHECK_RETURN
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:495
member_offset_bits
optionalt< mp_integer > member_offset_bits(const struct_typet &type, const irep_idt &member, const namespacet &ns)
Definition: pointer_offset_size.cpp:65
typet
The type of an expression, extends irept.
Definition: type.h:28
rw_range_sett::get_objects_dereference
virtual void get_objects_dereference(get_modet mode, const dereference_exprt &deref, const range_spect &range_start, const range_spect &size)
Definition: goto_rw.cpp:134
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
rw_guarded_range_set_value_sett::guard
guardt guard
Definition: goto_rw.h:502
guarded_range_domaint::begin
iterator begin()
Definition: goto_rw.h:441
rw_range_sett::get_modet::LHS_W
@ LHS_W
dereference_exprt
Operator to dereference a pointer.
Definition: pointer_expr.h:659
rw_range_sett::get_objects_typecast
virtual void get_objects_typecast(get_modet mode, const typecast_exprt &tc, const range_spect &range_start, const range_spect &size)
Definition: goto_rw.cpp:438
if_exprt
The trinary if-then-else operator.
Definition: std_expr.h:2322
object_descriptor_exprt
Split an expression into a base object and a (byte) offset.
Definition: pointer_expr.h:166
complex_real_exprt
Real part of the expression describing a complex number.
Definition: std_expr.h:1925
range_spect
Data type to describe upper and lower bounds of the range of bits that a read or write access may aff...
Definition: goto_rw.h:60
exprt
Base class for all expressions.
Definition: expr.h:55
rw_range_sett::~rw_range_sett
virtual ~rw_range_sett()
Definition: goto_rw.cpp:50
irep_idt
dstringt irep_idt
Definition: irep.h:37
vector_typet
The vector type.
Definition: std_types.h:1007
exprt::is_true
bool is_true() const
Return whether the expression is a constant representing true.
Definition: expr.cpp:34
rw_range_sett::get_objects_struct
virtual void get_objects_struct(get_modet mode, const struct_exprt &expr, const range_spect &range_start, const range_spect &size)
Definition: goto_rw.cpp:366
goto_functionst::function_map
function_mapt function_map
Definition: goto_functions.h:29
to_complex_type
const complex_typet & to_complex_type(const typet &type)
Cast a typet to a complex_typet.
Definition: std_types.h:1102
range_domaint::output
void output(const namespacet &ns, std::ostream &out) const override
Definition: goto_rw.cpp:36
symbol_exprt
Expression to hold a symbol (variable)
Definition: std_expr.h:112
shift_exprt::op
exprt & op()
Definition: bitvector_expr.h:239
goto_rw.h
rw_range_sett::get_objects_member
virtual void get_objects_member(get_modet mode, const member_exprt &expr, const range_spect &range_start, const range_spect &size)
Definition: goto_rw.cpp:239
if_exprt::false_case
exprt & false_case()
Definition: std_expr.h:2360
exprt::is_false
bool is_false() const
Return whether the expression is a constant representing false.
Definition: expr.cpp:43
object_descriptor_exprt::root_object
static const exprt & root_object(const exprt &expr)
Definition: pointer_expr.cpp:168
to_complex_real_expr
const complex_real_exprt & to_complex_real_expr(const exprt &expr)
Cast an exprt to a complex_real_exprt.
Definition: std_expr.h:1952
struct_exprt
Struct constructor from list of elements.
Definition: std_expr.h:1818
namespacet
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:90
rw_guarded_range_set_value_sett::get_objects_rec
void get_objects_rec(const irep_idt &_function, goto_programt::const_targett _target, get_modet mode, const exprt &expr) override
Definition: goto_rw.h:481
THROW
@ THROW
Definition: goto_program.h:50
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:84
irept::is_not_nil
bool is_not_nil() const
Definition: irep.h:380
array_exprt::type
const array_typet & type() const
Definition: std_expr.h:1570
GOTO
@ GOTO
Definition: goto_program.h:34
byte_operators.h
Expression classes for byte-level operators.
vector_typet::element_type
const typet & element_type() const
The type of the elements of the vector.
Definition: std_types.h:1026
rw_range_set_value_sett::get_objects_dereference
void get_objects_dereference(get_modet mode, const dereference_exprt &deref, const range_spect &range_start, const range_spect &size) override
Definition: goto_rw.cpp:674
make_unique.h
rw_range_sett::get_objects_rec
virtual void get_objects_rec(const irep_idt &, goto_programt::const_targett, get_modet mode, const exprt &expr)
Definition: goto_rw.h:239
rw_range_set_value_sett::value_sets
value_setst & value_sets
Definition: goto_rw.h:415
rw_range_sett
Definition: goto_rw.h:203
rw_range_set_value_sett::get_objects_rec
void get_objects_rec(const irep_idt &_function, goto_programt::const_targett _target, get_modet mode, const exprt &expr) override
Definition: goto_rw.h:379
byte_extract_exprt::op
exprt & op()
Definition: byte_operators.h:43
guard_exprt::as_expr
exprt as_expr() const
Definition: guard_expr.h:46
forall_operands
#define forall_operands(it, expr)
Definition: expr.h:20
language_util.h
member_exprt::struct_op
const exprt & struct_op() const
Definition: std_expr.h:2832
guard_exprt::add
void add(const exprt &expr)
Definition: guard_expr.cpp:39
PRECONDITION
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
symbol_exprt::get_identifier
const irep_idt & get_identifier() const
Definition: std_expr.h:142
dereference_exprt::pointer
exprt & pointer()
Definition: pointer_expr.h:673
pointer_offset_bits
optionalt< mp_integer > pointer_offset_bits(const typet &type, const namespacet &ns)
Definition: pointer_offset_size.cpp:101
endianness_mapt::map_bit
size_t map_bit(size_t bit) const
Definition: endianness_map.h:47
rw_guarded_range_set_value_sett::add
void add(get_modet mode, const irep_idt &identifier, const range_spect &range_start, const range_spect &range_end) override
Definition: goto_rw.cpp:756
pointer_expr.h
rw_range_sett::add
virtual void add(get_modet mode, const irep_idt &identifier, const range_spect &range_start, const range_spect &range_end)
Definition: goto_rw.cpp:518
irept::id_string
const std::string & id_string() const
Definition: irep.h:399
rw_range_sett::get_objects_complex_imag
virtual void get_objects_complex_imag(get_modet mode, const complex_imag_exprt &expr, const range_spect &range_start, const range_spect &size)
Definition: goto_rw.cpp:93
simplify_expr
exprt simplify_expr(exprt src, const namespacet &ns)
Definition: simplify_expr.cpp:2931
index_exprt::index
exprt & index()
Definition: std_expr.h:1450
rw_range_sett::get_objects_index
virtual void get_objects_index(get_modet mode, const index_exprt &expr, const range_spect &range_start, const range_spect &size)
Definition: goto_rw.cpp:271
NO_INSTRUCTION_TYPE
@ NO_INSTRUCTION_TYPE
Definition: goto_program.h:33
index_exprt::array
exprt & array()
Definition: std_expr.h:1440
range_domain_baset::~range_domain_baset
virtual ~range_domain_baset()
Definition: goto_rw.cpp:32
to_symbol_expr
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:222
rw_range_set_value_sett::target
goto_programt::const_targett target
Definition: goto_rw.h:417
OTHER
@ OTHER
Definition: goto_program.h:37
codet::op2
exprt & op2()
Definition: expr.h:131
irept::id
const irep_idt & id() const
Definition: irep.h:396
exprt::operandst
std::vector< exprt > operandst
Definition: expr.h:58
unary_exprt::op
const exprt & op() const
Definition: std_expr.h:326
END_FUNCTION
@ END_FUNCTION
Definition: goto_program.h:42
SKIP
@ SKIP
Definition: goto_program.h:38
std_code.h
to_complex_imag_expr
const complex_imag_exprt & to_complex_imag_expr(const exprt &expr)
Cast an exprt to a complex_imag_exprt.
Definition: std_expr.h:1997
rw_range_sett::output
void output(std::ostream &out) const
Definition: goto_rw.cpp:63
to_shift_expr
const shift_exprt & to_shift_expr(const exprt &expr)
Cast an exprt to a shift_exprt.
Definition: bitvector_expr.h:278
endianness_map.h
simplify_expr.h
byte_extract_exprt::offset
exprt & offset()
Definition: byte_operators.h:44
member_exprt
Extract member of struct or union.
Definition: std_expr.h:2793
expr_util.h
Deprecated expression utility functions.
ASSIGN
@ ASSIGN
Definition: goto_program.h:46
rw_range_sett::w_range_set
objectst w_range_set
Definition: goto_rw.h:267
goto_functionst
A collection of goto functions.
Definition: goto_functions.h:24
guarded_range_domaint
Definition: goto_rw.h:428
shift_exprt
A base class for shift and rotate operators.
Definition: bitvector_expr.h:229
rw_range_sett::ns
const namespacet & ns
Definition: goto_rw.h:265
struct_typet
Structure type, corresponds to C style structs.
Definition: std_types.h:230
CATCH
@ CATCH
Definition: goto_program.h:51
array_typet
Arrays with given size.
Definition: std_types.h:762
if_exprt::true_case
exprt & true_case()
Definition: std_expr.h:2350
DECL
@ DECL
Definition: goto_program.h:47
namespace_baset::follow
const typet & follow(const typet &) const
Resolve type symbol to the type it points to.
Definition: namespace.cpp:49
shift_exprt::distance
exprt & distance()
Definition: bitvector_expr.h:249
guarded_range_domaint::end
iterator end()
Definition: goto_rw.h:445
ASSUME
@ ASSUME
Definition: goto_program.h:35
to_typecast_expr
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition: std_expr.h:2051
if_exprt::cond
exprt & cond()
Definition: std_expr.h:2340
goto_program_dereference.h
goto_rw_other
static void goto_rw_other(const irep_idt &function, goto_programt::const_targett target, const codet &code, rw_range_sett &rw_set)
Definition: goto_rw.cpp:788
complex_imag_exprt
Imaginary part of the expression describing a complex number.
Definition: std_expr.h:1970
byte_extract_exprt
Expression of type type extracted from some object op starting at position offset (given in number of...
Definition: byte_operators.h:28
to_array_type
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition: std_types.h:844
START_THREAD
@ START_THREAD
Definition: goto_program.h:39
FUNCTION_CALL
@ FUNCTION_CALL
Definition: goto_program.h:49
endianness_mapt
Maps a big-endian offset to a little-endian offset.
Definition: endianness_map.h:30
goto_functions.h
goto_programt
A generic container class for the GOTO intermediate representation of one function.
Definition: goto_program.h:72
type_with_subtypet::subtype
const typet & subtype() const
Definition: type.h:172
to_vector_type
const vector_typet & to_vector_type(const typet &type)
Cast a typet to a vector_typet.
Definition: std_types.h:1060
rw_range_sett::get_objects_complex_real
virtual void get_objects_complex_real(get_modet mode, const complex_real_exprt &expr, const range_spect &range_start, const range_spect &size)
Definition: goto_rw.cpp:84
to_member_expr
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition: std_expr.h:2886
ATOMIC_END
@ ATOMIC_END
Definition: goto_program.h:44
goto_programt::const_targett
instructionst::const_iterator const_targett
Definition: goto_program.h:587
range_spect::unknown
static range_spect unknown()
Definition: goto_rw.h:69
goto_rw
static void goto_rw(const irep_idt &function, goto_programt::const_targett target, const exprt &lhs, const exprt &function_expr, const exprt::operandst &arguments, rw_range_sett &rw_set)
Definition: goto_rw.cpp:843
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
DEAD
@ DEAD
Definition: goto_program.h:48
exprt::operands
operandst & operands()
Definition: expr.h:94
guarded_range_domaint::output
virtual void output(const namespacet &ns, std::ostream &out) const override
Definition: goto_rw.cpp:712
codet::op1
exprt & op1()
Definition: expr.h:128
dereference
void dereference(const irep_idt &function_id, goto_programt::const_targett target, exprt &expr, const namespacet &ns, value_setst &value_sets)
Remove dereferences in expr using value_sets to determine to what objects the pointers may be pointin...
Definition: goto_program_dereference.cpp:278
index_exprt
Array index operator.
Definition: std_expr.h:1409
ATOMIC_BEGIN
@ ATOMIC_BEGIN
Definition: goto_program.h:43
address_of_exprt
Operator to return the address of an object.
Definition: pointer_expr.h:370
typecast_exprt
Semantic type conversion.
Definition: std_expr.h:2016
range_domaint::const_iterator
sub_typet::const_iterator const_iterator
Definition: goto_rw.h:185
codet::get_statement
const irep_idt & get_statement() const
Definition: std_code_base.h:65
rw_guarded_range_set_value_sett::get_objects_if
void get_objects_if(get_modet mode, const if_exprt &if_expr, const range_spect &range_start, const range_spect &size) override
Definition: goto_rw.cpp:730
LOCATION
@ LOCATION
Definition: goto_program.h:41
ASSERT
@ ASSERT
Definition: goto_program.h:36
goto_rw_assign
static void goto_rw_assign(const irep_idt &function, goto_programt::const_targett target, const exprt &lhs, const exprt &rhs, rw_range_sett &rw_set)
Definition: goto_rw.cpp:776
array_exprt
Array constructor from list of elements.
Definition: std_expr.h:1562
from_expr
std::string from_expr(const namespacet &ns, const irep_idt &identifier, const exprt &expr)
Definition: language_util.cpp:38
END_THREAD
@ END_THREAD
Definition: goto_program.h:40
INCOMPLETE_GOTO
@ INCOMPLETE_GOTO
Definition: goto_program.h:52
rw_range_sett::get_w_set
const objectst & get_w_set() const
Definition: goto_rw.h:225
forall_goto_program_instructions
#define forall_goto_program_instructions(it, program)
Definition: goto_program.h:1229
range_domaint::begin
iterator begin()
Definition: goto_rw.h:187
rw_range_sett::get_modet::READ
@ READ
bitvector_expr.h
rw_range_sett::get_modet
get_modet
Definition: goto_rw.h:237
to_struct_expr
const struct_exprt & to_struct_expr(const exprt &expr)
Cast an exprt to a struct_exprt.
Definition: std_expr.h:1842
rw_range_sett::r_range_set
objectst r_range_set
Definition: goto_rw.h:267
array_typet::element_type
const typet & element_type() const
The type of the elements of the array.
Definition: std_types.h:785
range_domaint::end
iterator end()
Definition: goto_rw.h:191
range_domaint
Definition: goto_rw.h:174
range_spect::to_range_spect
static range_spect to_range_spect(const mp_integer &size)
Definition: goto_rw.h:79
codet
Data structure for representing an arbitrary statement in a program.
Definition: std_code_base.h:28
not_exprt
Boolean negation.
Definition: std_expr.h:2277