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