CBMC
value_set_fi.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Value Set (Flow Insensitive, Sharing)
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
11 
12 #include "value_set_fi.h"
13 
14 #include <util/arith_tools.h>
15 #include <util/byte_operators.h>
16 #include <util/c_types.h>
17 #include <util/expr_util.h>
18 #include <util/namespace.h>
19 #include <util/pointer_expr.h>
20 #include <util/prefix.h>
21 #include <util/simplify_expr.h>
22 #include <util/std_code.h>
23 #include <util/symbol.h>
24 
26 
27 #include <langapi/language_util.h>
28 
29 #include <ostream>
30 
32 
35 
36 static const char *alloc_adapter_prefix="alloc_adaptor::";
37 
39  const namespacet &ns,
40  std::ostream &out) const
41 {
42  for(valuest::const_iterator
43  v_it=values.begin();
44  v_it!=values.end();
45  v_it++)
46  {
47  irep_idt identifier, display_name;
48 
49  const entryt &e=v_it->second;
50 
51  if(has_prefix(id2string(e.identifier), "value_set::dynamic_object"))
52  {
53  display_name=id2string(e.identifier)+e.suffix;
54  identifier.clear();
55  }
56  else
57  {
58  #if 0
59  const symbolt &symbol=ns.lookup(id2string(e.identifier));
60  display_name=symbol.display_name()+e.suffix;
61  identifier=symbol.name;
62  #else
63  identifier=id2string(e.identifier);
64  display_name=id2string(identifier)+e.suffix;
65  #endif
66  }
67 
68  out << display_name;
69 
70  out << " = { ";
71 
72  object_mapt object_map;
73  flatten(e, object_map);
74 
75  std::size_t width=0;
76 
77  const auto &entries = object_map.read();
78  for(object_map_dt::const_iterator o_it = entries.begin();
79  o_it != entries.end();
80  ++o_it)
81  {
82  const exprt &o=object_numbering[o_it->first];
83 
84  std::string result;
85 
86  if(o.id()==ID_invalid || o.id()==ID_unknown)
87  {
88  result="<";
89  result+=from_expr(ns, identifier, o);
90  result+=", *, "; // offset unknown
91  if(o.type().id()==ID_unknown)
92  result+='*';
93  else
94  result+=from_type(ns, identifier, o.type());
95  result+='>';
96  }
97  else
98  {
99  result="<"+from_expr(ns, identifier, o)+", ";
100 
101  if(o_it->second)
102  result += integer2string(*o_it->second);
103  else
104  result+='*';
105 
106  result+=", ";
107 
108  if(o.type().id()==ID_unknown)
109  result+='*';
110  else
111  result+=from_type(ns, identifier, o.type());
112 
113  result+='>';
114  }
115 
116  out << result;
117 
118  width+=result.size();
119 
121  next++;
122 
123  if(next != entries.end())
124  {
125  out << ", ";
126  if(width>=40)
127  out << "\n ";
128  }
129  }
130 
131  out << " } \n";
132  }
133 }
134 
136  const entryt &e,
137  object_mapt &dest) const
138 {
139  #if 0
140  std::cout << "FLATTEN: " << e.identifier << e.suffix << '\n';
141  #endif
142 
143  flatten_seent seen;
144  flatten_rec(e, dest, seen);
145 
146  #if 0
147  std::cout << "FLATTEN: Done.\n";
148  #endif
149 }
150 
152  const entryt &e,
153  object_mapt &dest,
154  flatten_seent &seen) const
155 {
156  #if 0
157  std::cout << "FLATTEN_REC: " << e.identifier << e.suffix << '\n';
158  #endif
159 
160  std::string identifier = id2string(e.identifier);
161  assert(seen.find(identifier + e.suffix)==seen.end());
162 
163  bool generalize_index = false;
164 
165  seen.insert(identifier + e.suffix);
166 
167  for(const auto &object_entry : e.object_map.read())
168  {
169  const exprt &o = object_numbering[object_entry.first];
170 
171  if(o.type().id()=="#REF#")
172  {
173  if(seen.find(o.get(ID_identifier))!=seen.end())
174  {
175  generalize_index = true;
176  continue;
177  }
178 
179  valuest::const_iterator fi = values.find(o.get(ID_identifier));
180  if(fi==values.end())
181  {
182  // this is some static object, keep it in.
183  const symbol_exprt se(
184  o.get(ID_identifier), to_type_with_subtype(o.type()).subtype());
185  insert(dest, se, mp_integer{0});
186  }
187  else
188  {
189  object_mapt temp;
190  flatten_rec(fi->second, temp, seen);
191 
192  for(object_map_dt::iterator t_it=temp.write().begin();
193  t_it!=temp.write().end();
194  t_it++)
195  {
196  if(t_it->second && object_entry.second)
197  {
198  *t_it->second += *object_entry.second;
199  }
200  else
201  t_it->second.reset();
202  }
203 
204  for(const auto &object_entry : temp.read())
205  insert(dest, object_entry);
206  }
207  }
208  else
209  insert(dest, object_entry);
210  }
211 
212  if(generalize_index) // this means we had recursive symbols in there
213  {
214  for(auto &object_entry : dest.write())
215  object_entry.second.reset();
216  }
217 
218  seen.erase(identifier + e.suffix);
219 }
220 
222 {
223  const exprt &object=object_numbering[it.first];
224 
225  if(object.id()==ID_invalid ||
226  object.id()==ID_unknown)
227  return object;
228 
230 
231  od.object()=object;
232 
233  if(it.second)
234  od.offset() = from_integer(*it.second, c_index_type());
235 
236  od.type()=od.object().type();
237 
238  return std::move(od);
239 }
240 
242 {
243  UNREACHABLE;
244  bool result=false;
245 
246  for(valuest::const_iterator
247  it=new_values.begin();
248  it!=new_values.end();
249  it++)
250  {
251  valuest::iterator it2=values.find(it->first);
252 
253  if(it2==values.end())
254  {
255  // we always track these
256  if(has_prefix(id2string(it->second.identifier),
257  "value_set::dynamic_object") ||
258  has_prefix(id2string(it->second.identifier),
259  "value_set::return_value"))
260  {
261  values.insert(*it);
262  result=true;
263  }
264 
265  continue;
266  }
267 
268  entryt &e=it2->second;
269  const entryt &new_e=it->second;
270 
271  if(make_union(e.object_map, new_e.object_map))
272  result=true;
273  }
274 
275  changed = result;
276 
277  return result;
278 }
279 
280 bool value_set_fit::make_union(object_mapt &dest, const object_mapt &src) const
281 {
282  bool result=false;
283 
284  for(const auto &object_entry : src.read())
285  {
286  if(insert(dest, object_entry))
287  result=true;
288  }
289 
290  return result;
291 }
292 
293 std::vector<exprt>
294 value_set_fit::get_value_set(const exprt &expr, const namespacet &ns) const
295 {
296  object_mapt object_map;
297  get_value_set(expr, object_map, ns);
298 
299  object_mapt flat_map;
300 
301  for(const auto &object_entry : object_map.read())
302  {
303  const exprt &object = object_numbering[object_entry.first];
304  if(object.type().id()=="#REF#")
305  {
306  assert(object.id()==ID_symbol);
307 
308  const irep_idt &ident = object.get(ID_identifier);
309  valuest::const_iterator v_it = values.find(ident);
310 
311  if(v_it!=values.end())
312  {
313  object_mapt temp;
314  flatten(v_it->second, temp);
315 
316  for(object_map_dt::iterator t_it=temp.write().begin();
317  t_it!=temp.write().end();
318  t_it++)
319  {
320  if(t_it->second && object_entry.second)
321  {
322  *t_it->second += *object_entry.second;
323  }
324  else
325  t_it->second.reset();
326 
327  flat_map.write()[t_it->first]=t_it->second;
328  }
329  }
330  }
331  else
332  flat_map.write()[object_entry.first] = object_entry.second;
333  }
334 
335  std::vector<exprt> result;
336  for(const auto &object_entry : flat_map.read())
337  result.push_back(to_expr(object_entry));
338 
339 #if 0
340  // Sanity check!
341  for(std::list<exprt>::const_iterator it=value_set.begin();
342  it!=value_set.end();
343  it++)
344  assert(it->type().id()!="#REF");
345 #endif
346 
347 #if 0
348  for(expr_sett::const_iterator it=value_set.begin(); it!=value_set.end(); it++)
349  std::cout << "GET_VALUE_SET: " << format(*it) << '\n';
350 #endif
351 
352  return result;
353 }
354 
356  const exprt &expr,
357  object_mapt &dest,
358  const namespacet &ns) const
359 {
360  exprt tmp(expr);
361  simplify(tmp, ns);
362 
363  gvs_recursion_sett recset;
364  get_value_set_rec(tmp, dest, "", tmp.type(), ns, recset);
365 }
366 
368  const exprt &expr,
369  object_mapt &dest,
370  const std::string &suffix,
371  const typet &original_type,
372  const namespacet &ns,
373  gvs_recursion_sett &recursion_set) const
374 {
375  #if 0
376  std::cout << "GET_VALUE_SET_REC EXPR: " << format(expr)
377  << '\n';
378  std::cout << "GET_VALUE_SET_REC SUFFIX: " << suffix << '\n';
379  std::cout << '\n';
380  #endif
381 
382  if(expr.type().id()=="#REF#")
383  {
384  valuest::const_iterator fi = values.find(expr.get(ID_identifier));
385 
386  if(fi!=values.end())
387  {
388  for(const auto &object_entry : fi->second.object_map.read())
389  {
391  object_numbering[object_entry.first],
392  dest,
393  suffix,
394  original_type,
395  ns,
396  recursion_set);
397  }
398  return;
399  }
400  else
401  {
402  insert(dest, exprt(ID_unknown, original_type));
403  return;
404  }
405  }
406  else if(expr.id()==ID_unknown || expr.id()==ID_invalid)
407  {
408  insert(dest, exprt(ID_unknown, original_type));
409  return;
410  }
411  else if(expr.id()==ID_index)
412  {
413  const typet &type = to_index_expr(expr).array().type();
414 
415  if(type.id() == ID_array)
416  {
418  to_index_expr(expr).array(),
419  dest,
420  "[]" + suffix,
421  original_type,
422  ns,
423  recursion_set);
424  }
425  else
426  insert(dest, exprt(ID_unknown, original_type));
427 
428  return;
429  }
430  else if(expr.id()==ID_member)
431  {
432  const auto &compound = to_member_expr(expr).compound();
433 
434  if(compound.is_not_nil())
435  {
436  const typet &type = ns.follow(compound.type());
437 
439  type.id() == ID_struct || type.id() == ID_union,
440  "operand 0 of member expression must be struct or union");
441 
442  const std::string &component_name =
443  id2string(to_member_expr(expr).get_component_name());
444 
446  compound,
447  dest,
448  "." + component_name + suffix,
449  original_type,
450  ns,
451  recursion_set);
452 
453  return;
454  }
455  }
456  else if(expr.id()==ID_symbol)
457  {
458  // just keep a reference to the ident in the set
459  // (if it exists)
460  irep_idt ident = id2string(to_symbol_expr(expr).get_identifier()) + suffix;
461  valuest::const_iterator v_it=values.find(ident);
462 
464  {
465  insert(dest, expr, mp_integer{0});
466  return;
467  }
468  else if(v_it!=values.end())
469  {
470  type_with_subtypet t("#REF#", expr.type());
471  symbol_exprt sym(ident, t);
472  insert(dest, sym, mp_integer{0});
473  return;
474  }
475  }
476  else if(expr.id()==ID_if)
477  {
479  to_if_expr(expr).true_case(),
480  dest,
481  suffix,
482  original_type,
483  ns,
484  recursion_set);
486  to_if_expr(expr).false_case(),
487  dest,
488  suffix,
489  original_type,
490  ns,
491  recursion_set);
492 
493  return;
494  }
495  else if(expr.id()==ID_address_of)
496  {
497  get_reference_set_sharing(to_address_of_expr(expr).object(), dest, ns);
498 
499  return;
500  }
501  else if(expr.id()==ID_dereference)
502  {
503  object_mapt reference_set;
504  get_reference_set_sharing(expr, reference_set, ns);
505  const object_map_dt &object_map=reference_set.read();
506 
507  if(object_map.begin()!=object_map.end())
508  {
509  for(const auto &object_entry : object_map)
510  {
511  const exprt &object = object_numbering[object_entry.first];
512  get_value_set_rec(object, dest, suffix,
513  original_type, ns, recursion_set);
514  }
515 
516  return;
517  }
518  }
519  else if(expr.is_constant())
520  {
521  // check if NULL
523  {
524  insert(
525  dest,
526  exprt(ID_null_object, to_pointer_type(expr.type()).base_type()),
527  mp_integer{0});
528  return;
529  }
530  }
531  else if(expr.id()==ID_typecast)
532  {
534  to_typecast_expr(expr).op(),
535  dest,
536  suffix,
537  original_type,
538  ns,
539  recursion_set);
540 
541  return;
542  }
543  else if(expr.id()==ID_plus || expr.id()==ID_minus)
544  {
545  if(expr.operands().size()<2)
546  throw expr.id_string()+" expected to have at least two operands";
547 
548  if(expr.type().id()==ID_pointer)
549  {
550  // find the pointer operand
551  const exprt *ptr_operand=nullptr;
552 
553  forall_operands(it, expr)
554  if(it->type().id()==ID_pointer)
555  {
556  if(ptr_operand==nullptr)
557  ptr_operand=&(*it);
558  else
559  throw "more than one pointer operand in pointer arithmetic";
560  }
561 
562  if(ptr_operand==nullptr)
563  throw "pointer type sum expected to have pointer operand";
564 
565  object_mapt pointer_expr_set;
566  get_value_set_rec(*ptr_operand, pointer_expr_set, "",
567  ptr_operand->type(), ns, recursion_set);
568 
569  for(const auto &object_entry : pointer_expr_set.read())
570  {
571  offsett offset = object_entry.second;
572 
573  if(offset_is_zero(offset) && expr.operands().size() == 2)
574  {
575  if(to_binary_expr(expr).op0().type().id() != ID_pointer)
576  {
577  const auto i = numeric_cast<mp_integer>(to_binary_expr(expr).op0());
578  if(!i.has_value())
579  offset.reset();
580  else
581  *offset = (expr.id() == ID_plus) ? *i : -*i;
582  }
583  else
584  {
585  const auto i = numeric_cast<mp_integer>(to_binary_expr(expr).op1());
586  if(!i.has_value())
587  offset.reset();
588  else
589  *offset = (expr.id() == ID_plus) ? *i : -*i;
590  }
591  }
592  else
593  offset.reset();
594 
595  insert(dest, object_entry.first, offset);
596  }
597 
598  return;
599  }
600  }
601  else if(expr.id()==ID_side_effect)
602  {
603  const irep_idt &statement = to_side_effect_expr(expr).get_statement();
604 
605  if(statement==ID_function_call)
606  {
607  // these should be gone
608  throw "unexpected function_call sideeffect";
609  }
610  else if(statement==ID_allocate)
611  {
612  if(expr.type().id()!=ID_pointer)
613  throw "malloc expected to return pointer type";
614 
615  PRECONDITION(suffix.empty());
616 
617  const typet &dynamic_type=
618  static_cast<const typet &>(expr.find(ID_C_cxx_alloc_type));
619 
620  dynamic_object_exprt dynamic_object(dynamic_type);
621  // let's make up a `unique' number for this object...
622  dynamic_object.set_instance(
623  (from_function << 16) | from_target_index);
624  dynamic_object.valid()=true_exprt();
625 
626  insert(dest, dynamic_object, mp_integer{0});
627  return;
628  }
629  else if(statement==ID_cpp_new ||
630  statement==ID_cpp_new_array)
631  {
632  PRECONDITION(suffix.empty());
633  assert(expr.type().id()==ID_pointer);
634 
635  dynamic_object_exprt dynamic_object(
636  to_pointer_type(expr.type()).base_type());
637  dynamic_object.set_instance(
638  (from_function << 16) | from_target_index);
639  dynamic_object.valid()=true_exprt();
640 
641  insert(dest, dynamic_object, mp_integer{0});
642  return;
643  }
644  }
645  else if(expr.id()==ID_struct)
646  {
647  // this is like a static struct object
648  insert(dest, address_of_exprt(expr), mp_integer{0});
649  return;
650  }
651  else if(expr.id()==ID_with)
652  {
653  // these are supposed to be done by assign()
654  throw "unexpected value in get_value_set: "+expr.id_string();
655  }
656  else if(expr.id()==ID_array_of ||
657  expr.id()==ID_array)
658  {
659  // an array constructor, possibly containing addresses
660  forall_operands(it, expr)
661  get_value_set_rec(*it, dest, suffix, original_type, ns, recursion_set);
662  }
663  else if(expr.id()==ID_dynamic_object)
664  {
665  const dynamic_object_exprt &dynamic_object=
667 
668  const std::string name=
669  "value_set::dynamic_object"+
670  std::to_string(dynamic_object.get_instance())+
671  suffix;
672 
673  // look it up
674  valuest::const_iterator v_it=values.find(name);
675 
676  if(v_it!=values.end())
677  {
678  make_union(dest, v_it->second.object_map);
679  return;
680  }
681  }
682 
683  insert(dest, exprt(ID_unknown, original_type));
684 }
685 
687  const exprt &src,
688  exprt &dest) const
689 {
690  // remove pointer typecasts
691  if(src.id()==ID_typecast)
692  {
693  assert(src.type().id()==ID_pointer);
694 
695  dereference_rec(to_typecast_expr(src).op(), dest);
696  }
697  else
698  dest=src;
699 }
700 
702  const exprt &expr,
703  expr_sett &dest,
704  const namespacet &ns) const
705 {
706  object_mapt object_map;
707  get_reference_set_sharing(expr, object_map, ns);
708 
709  for(const auto &object_entry : object_map.read())
710  {
711  const exprt &object = object_numbering[object_entry.first];
712 
713  if(object.type().id() == "#REF#")
714  {
715  const irep_idt &ident = object.get(ID_identifier);
716  valuest::const_iterator vit = values.find(ident);
717  if(vit==values.end())
718  {
719  // Assume the variable never was assigned,
720  // so assume it's reference set is unknown.
721  dest.insert(exprt(ID_unknown, object.type()));
722  }
723  else
724  {
725  object_mapt omt;
726  flatten(vit->second, omt);
727 
728  for(object_map_dt::iterator t_it=omt.write().begin();
729  t_it!=omt.write().end();
730  t_it++)
731  {
732  if(t_it->second && object_entry.second)
733  {
734  *t_it->second += *object_entry.second;
735  }
736  else
737  t_it->second.reset();
738  }
739 
740  for(const auto &o : omt.read())
741  dest.insert(to_expr(o));
742  }
743  }
744  else
745  dest.insert(to_expr(object_entry));
746  }
747 }
748 
750  const exprt &expr,
751  expr_sett &dest,
752  const namespacet &ns) const
753 {
754  object_mapt object_map;
755  get_reference_set_sharing(expr, object_map, ns);
756 
757  for(const auto &object_entry : object_map.read())
758  dest.insert(to_expr(object_entry));
759 }
760 
762  const exprt &expr,
763  object_mapt &dest,
764  const namespacet &ns) const
765 {
766  #if 0
767  std::cout << "GET_REFERENCE_SET_REC EXPR: " << format(expr)
768  << '\n';
769  #endif
770 
771  if(expr.type().id()=="#REF#")
772  {
773  valuest::const_iterator fi = values.find(expr.get(ID_identifier));
774  if(fi!=values.end())
775  {
776  for(const auto &object_entry : fi->second.object_map.read())
777  {
779  object_numbering[object_entry.first], dest, ns);
780  }
781  return;
782  }
783  }
784  else if(expr.id()==ID_symbol ||
785  expr.id()==ID_dynamic_object ||
786  expr.id()==ID_string_constant)
787  {
788  if(
789  expr.type().id() == ID_array &&
790  to_array_type(expr.type()).element_type().id() == ID_array)
791  {
792  insert(dest, expr);
793  }
794  else
795  insert(dest, expr, mp_integer{0});
796 
797  return;
798  }
799  else if(expr.id()==ID_dereference)
800  {
801  gvs_recursion_sett recset;
802  object_mapt temp;
804  to_dereference_expr(expr).pointer(),
805  temp,
806  "",
807  to_dereference_expr(expr).pointer().type(),
808  ns,
809  recset);
810 
811  // REF's need to be dereferenced manually!
812  for(const auto &object_entry : temp.read())
813  {
814  const exprt &obj = object_numbering[object_entry.first];
815  if(obj.type().id()=="#REF#")
816  {
817  const irep_idt &ident = obj.get(ID_identifier);
818  valuest::const_iterator v_it = values.find(ident);
819 
820  if(v_it!=values.end())
821  {
822  object_mapt t2;
823  flatten(v_it->second, t2);
824 
825  for(object_map_dt::iterator t_it=t2.write().begin();
826  t_it!=t2.write().end();
827  t_it++)
828  {
829  if(t_it->second && object_entry.second)
830  {
831  *t_it->second += *object_entry.second;
832  }
833  else
834  t_it->second.reset();
835  }
836 
837  for(const auto &t2_object_entry : t2.read())
838  insert(dest, t2_object_entry);
839  }
840  else
841  insert(
842  dest,
843  exprt(ID_unknown, to_type_with_subtype(obj.type()).subtype()));
844  }
845  else
846  insert(dest, object_entry);
847  }
848 
849  #if 0
850  for(expr_sett::const_iterator it=value_set.begin();
851  it!=value_set.end();
852  it++)
853  std::cout << "VALUE_SET: " << format(*it) << '\n';
854  #endif
855 
856  return;
857  }
858  else if(expr.id()==ID_index)
859  {
860  const exprt &array = to_index_expr(expr).array();
861  const exprt &offset = to_index_expr(expr).index();
862  const typet &array_type = array.type();
863 
865  array_type.id() == ID_array, "index takes array-typed operand");
866 
867  object_mapt array_references;
868  get_reference_set_sharing(array, array_references, ns);
869 
870  const object_map_dt &object_map=array_references.read();
871 
872  for(const auto &object_entry : object_map)
873  {
874  const exprt &object = object_numbering[object_entry.first];
875 
876  if(object.id()==ID_unknown)
877  insert(dest, exprt(ID_unknown, expr.type()));
878  else
879  {
880  index_exprt index_expr(
881  object, from_integer(0, c_index_type()), expr.type());
882 
883  exprt casted_index;
884 
885  // adjust type?
886  if(object.type().id() != "#REF#" && object.type() != array_type)
887  casted_index = typecast_exprt(index_expr, array.type());
888  else
889  casted_index = index_expr;
890 
891  offsett o = object_entry.second;
892  const auto i = numeric_cast<mp_integer>(offset);
893 
894  if(offset.is_zero())
895  {
896  }
897  else if(i.has_value() && offset_is_zero(o))
898  *o = *i;
899  else
900  o.reset();
901 
902  insert(dest, casted_index, o);
903  }
904  }
905 
906  return;
907  }
908  else if(expr.id()==ID_member)
909  {
910  const irep_idt &component_name=expr.get(ID_component_name);
911 
912  const exprt &struct_op = to_member_expr(expr).compound();
913 
914  object_mapt struct_references;
915  get_reference_set_sharing(struct_op, struct_references, ns);
916 
917  for(const auto &object_entry : struct_references.read())
918  {
919  const exprt &object = object_numbering[object_entry.first];
920  const typet &obj_type = object.type();
921 
922  if(object.id()==ID_unknown)
923  insert(dest, exprt(ID_unknown, expr.type()));
924  else if(
925  obj_type.id() != ID_struct && obj_type.id() != ID_union &&
926  obj_type.id() != ID_struct_tag && obj_type.id() != ID_union_tag)
927  {
928  // we catch objects of the wrong type,
929  // to avoid non-integral typecasts.
930  insert(dest, exprt(ID_unknown, expr.type()));
931  }
932  else
933  {
934  offsett o = object_entry.second;
935 
936  member_exprt member_expr(object, component_name, expr.type());
937 
938  // adjust type?
939  if(ns.follow(struct_op.type())!=ns.follow(object.type()))
940  {
941  member_expr.compound() =
942  typecast_exprt(member_expr.compound(), struct_op.type());
943  }
944 
945  insert(dest, member_expr, o);
946  }
947  }
948 
949  return;
950  }
951  else if(expr.id()==ID_if)
952  {
953  get_reference_set_sharing_rec(to_if_expr(expr).true_case(), dest, ns);
954  get_reference_set_sharing_rec(to_if_expr(expr).false_case(), dest, ns);
955  return;
956  }
957 
958  insert(dest, exprt(ID_unknown, expr.type()));
959 }
960 
962  const exprt &lhs,
963  const exprt &rhs,
964  const namespacet &ns)
965 {
966  #if 0
967  std::cout << "ASSIGN LHS: " << format(lhs) << '\n';
968  std::cout << "ASSIGN RHS: " << format(rhs) << '\n';
969  #endif
970 
971  if(rhs.id()==ID_if)
972  {
973  assign(lhs, to_if_expr(rhs).true_case(), ns);
974  assign(lhs, to_if_expr(rhs).false_case(), ns);
975  return;
976  }
977 
978  const typet &type=ns.follow(lhs.type());
979 
980  if(type.id()==ID_struct ||
981  type.id()==ID_union)
982  {
983  const struct_union_typet &struct_type=to_struct_union_type(type);
984 
985  std::size_t no=0;
986 
987  for(struct_typet::componentst::const_iterator
988  c_it=struct_type.components().begin();
989  c_it!=struct_type.components().end();
990  c_it++, no++)
991  {
992  const typet &subtype=c_it->type();
993  const irep_idt &name = c_it->get_name();
994 
995  // ignore methods
996  if(subtype.id()==ID_code)
997  continue;
998 
999  member_exprt lhs_member(lhs, name, subtype);
1000 
1001  exprt rhs_member;
1002 
1003  if(rhs.id()==ID_unknown ||
1004  rhs.id()==ID_invalid)
1005  {
1006  rhs_member=exprt(rhs.id(), subtype);
1007  }
1008  else
1009  {
1010  if(rhs.type() != lhs.type())
1011  throw "value_set_fit::assign type mismatch: "
1012  "rhs.type():\n"+rhs.type().pretty()+"\n"+
1013  "type:\n"+lhs.type().pretty();
1014 
1015  if(rhs.id()==ID_struct ||
1016  rhs.id()==ID_constant)
1017  {
1018  assert(no<rhs.operands().size());
1019  rhs_member=rhs.operands()[no];
1020  }
1021  else if(rhs.id()==ID_with)
1022  {
1023  // see if this is the member we want
1024  const auto &rhs_with = to_with_expr(rhs);
1025  const exprt &member_operand = rhs_with.where();
1026 
1027  const irep_idt &component_name=
1028  member_operand.get(ID_component_name);
1029 
1030  if(component_name==name)
1031  {
1032  // yes! just take op2
1033  rhs_member = rhs_with.new_value();
1034  }
1035  else
1036  {
1037  // no! do op0
1038  rhs_member=exprt(ID_member, subtype);
1039  rhs_member.copy_to_operands(rhs_with.old());
1040  rhs_member.set(ID_component_name, name);
1041  }
1042  }
1043  else
1044  {
1045  rhs_member=exprt(ID_member, subtype);
1046  rhs_member.copy_to_operands(rhs);
1047  rhs_member.set(ID_component_name, name);
1048  }
1049 
1050  assign(lhs_member, rhs_member, ns);
1051  }
1052  }
1053  }
1054  else if(type.id()==ID_array)
1055  {
1056  const index_exprt lhs_index(
1057  lhs,
1058  exprt(ID_unknown, c_index_type()),
1059  to_array_type(type).element_type());
1060 
1061  if(rhs.id()==ID_unknown ||
1062  rhs.id()==ID_invalid)
1063  {
1064  assign(
1065  lhs_index, exprt(rhs.id(), to_array_type(type).element_type()), ns);
1066  }
1067  else if(rhs.is_nil())
1068  {
1069  // do nothing
1070  }
1071  else
1072  {
1073  if(rhs.type() != type)
1074  throw "value_set_fit::assign type mismatch: "
1075  "rhs.type():\n"+rhs.type().pretty()+"\n"+
1076  "type:\n"+type.pretty();
1077 
1078  if(rhs.id()==ID_array_of)
1079  {
1080  assign(lhs_index, to_array_of_expr(rhs).what(), ns);
1081  }
1082  else if(rhs.id()==ID_array ||
1083  rhs.id()==ID_constant)
1084  {
1085  forall_operands(o_it, rhs)
1086  {
1087  assign(lhs_index, *o_it, ns);
1088  }
1089  }
1090  else if(rhs.id()==ID_with)
1091  {
1092  const index_exprt op0_index(
1093  to_with_expr(rhs).old(),
1094  exprt(ID_unknown, c_index_type()),
1095  to_array_type(type).element_type());
1096 
1097  assign(lhs_index, op0_index, ns);
1098  assign(lhs_index, to_with_expr(rhs).new_value(), ns);
1099  }
1100  else
1101  {
1102  const index_exprt rhs_index(
1103  rhs,
1104  exprt(ID_unknown, c_index_type()),
1105  to_array_type(type).element_type());
1106  assign(lhs_index, rhs_index, ns);
1107  }
1108  }
1109  }
1110  else
1111  {
1112  // basic type
1113  object_mapt values_rhs;
1114 
1115  get_value_set(rhs, values_rhs, ns);
1116 
1117  assign_recursion_sett recset;
1118  assign_rec(lhs, values_rhs, "", ns, recset);
1119  }
1120 }
1121 
1123  const exprt &lhs,
1124  const object_mapt &values_rhs,
1125  const std::string &suffix,
1126  const namespacet &ns,
1127  assign_recursion_sett &recursion_set)
1128 {
1129  #if 0
1130  std::cout << "ASSIGN_REC LHS: " << format(lhs) << '\n';
1131  std::cout << "ASSIGN_REC SUFFIX: " << suffix << '\n';
1132 
1133  for(object_map_dt::const_iterator it=values_rhs.read().begin();
1134  it!=values_rhs.read().end(); it++)
1135  std::cout << "ASSIGN_REC RHS: " << to_expr(it) << '\n';
1136  #endif
1137 
1138  if(lhs.type().id()=="#REF#")
1139  {
1140  const irep_idt &ident = lhs.get(ID_identifier);
1141  object_mapt temp;
1142  gvs_recursion_sett recset;
1144  lhs, temp, "", to_type_with_subtype(lhs.type()).subtype(), ns, recset);
1145 
1146  if(recursion_set.find(ident)!=recursion_set.end())
1147  {
1148  recursion_set.insert(ident);
1149 
1150  for(const auto &object_entry : temp.read())
1151  {
1152  const exprt &object = object_numbering[object_entry.first];
1153 
1154  if(object.id() != ID_unknown)
1155  assign_rec(object, values_rhs, suffix, ns, recursion_set);
1156  }
1157 
1158  recursion_set.erase(ident);
1159  }
1160  }
1161  else if(lhs.id()==ID_symbol)
1162  {
1163  const irep_idt &identifier = to_symbol_expr(lhs).get_identifier();
1164 
1165  if(has_prefix(id2string(identifier),
1166  "value_set::dynamic_object") ||
1167  has_prefix(id2string(identifier),
1168  "value_set::return_value") ||
1169  values.find(id2string(identifier)+suffix)!=values.end())
1170  // otherwise we don't track this value
1171  {
1172  entryt &entry = get_entry(identifier, suffix);
1173 
1174  if(make_union(entry.object_map, values_rhs))
1175  changed = true;
1176  }
1177  }
1178  else if(lhs.id()==ID_dynamic_object)
1179  {
1180  const dynamic_object_exprt &dynamic_object=
1182 
1183  const std::string name=
1184  "value_set::dynamic_object"+
1185  std::to_string(dynamic_object.get_instance());
1186 
1187  if(make_union(get_entry(name, suffix).object_map, values_rhs))
1188  changed = true;
1189  }
1190  else if(lhs.id()==ID_dereference)
1191  {
1192  if(lhs.operands().size()!=1)
1193  throw lhs.id_string()+" expected to have one operand";
1194 
1195  object_mapt reference_set;
1196  get_reference_set_sharing(lhs, reference_set, ns);
1197 
1198  for(const auto &object_entry : reference_set.read())
1199  {
1200  const exprt &object = object_numbering[object_entry.first];
1201 
1202  if(object.id()!=ID_unknown)
1203  assign_rec(object, values_rhs, suffix, ns, recursion_set);
1204  }
1205  }
1206  else if(lhs.id()==ID_index)
1207  {
1208  const typet &type = to_index_expr(lhs).array().type();
1209 
1210  if(type.id() == ID_array)
1211  {
1212  assign_rec(
1213  to_index_expr(lhs).array(),
1214  values_rhs,
1215  "[]" + suffix,
1216  ns,
1217  recursion_set);
1218  }
1219  }
1220  else if(lhs.id()==ID_member)
1221  {
1222  if(to_member_expr(lhs).compound().is_nil())
1223  return;
1224 
1225  const std::string &component_name=lhs.get_string(ID_component_name);
1226 
1227  const typet &type = ns.follow(to_member_expr(lhs).compound().type());
1228 
1230  type.id() == ID_struct || type.id() == ID_union,
1231  "operand 0 of member expression must be struct or union");
1232 
1233  assign_rec(
1234  to_member_expr(lhs).compound(),
1235  values_rhs,
1236  "." + component_name + suffix,
1237  ns,
1238  recursion_set);
1239  }
1240  else if(lhs.id()=="valid_object" ||
1241  lhs.id()=="dynamic_type")
1242  {
1243  // we ignore this here
1244  }
1245  else if(lhs.id()==ID_string_constant)
1246  {
1247  // someone writes into a string-constant
1248  // evil guy
1249  }
1250  else if(lhs.id() == ID_null_object)
1251  {
1252  // evil as well
1253  }
1254  else if(lhs.id()==ID_typecast)
1255  {
1256  const typecast_exprt &typecast_expr=to_typecast_expr(lhs);
1257 
1258  assign_rec(typecast_expr.op(), values_rhs, suffix, ns, recursion_set);
1259  }
1260  else if(
1261  lhs.id() == "zero_string" || lhs.id() == "is_zero_string" ||
1262  lhs.id() == "zero_string_length" || lhs.id() == ID_address_of)
1263  {
1264  // ignore
1265  }
1266  else if(lhs.id()==ID_byte_extract_little_endian ||
1267  lhs.id()==ID_byte_extract_big_endian)
1268  {
1269  assign_rec(
1270  to_byte_extract_expr(lhs).op(), values_rhs, suffix, ns, recursion_set);
1271  }
1272  else
1273  throw "assign NYI: '" + lhs.id_string() + "'";
1274 }
1275 
1277  const irep_idt &function,
1278  const exprt::operandst &arguments,
1279  const namespacet &ns)
1280 {
1281  const symbolt &symbol=ns.lookup(function);
1282 
1283  const code_typet &type=to_code_type(symbol.type);
1284  const code_typet::parameterst &parameter_types=type.parameters();
1285 
1286  // these first need to be assigned to dummy, temporary arguments
1287  // and only thereafter to the actuals, in order
1288  // to avoid overwriting actuals that are needed for recursive
1289  // calls
1290 
1291  for(std::size_t i=0; i<arguments.size(); i++)
1292  {
1293  const std::string identifier="value_set::" + id2string(function) + "::" +
1294  "argument$"+std::to_string(i);
1295  add_var(identifier);
1296  const symbol_exprt dummy_lhs(identifier, arguments[i].type());
1297  assign(dummy_lhs, arguments[i], ns);
1298  }
1299 
1300  // now assign to 'actual actuals'
1301 
1302  std::size_t i=0;
1303 
1304  for(code_typet::parameterst::const_iterator
1305  it=parameter_types.begin();
1306  it!=parameter_types.end();
1307  it++)
1308  {
1309  const irep_idt &identifier=it->get_identifier();
1310  if(identifier.empty())
1311  continue;
1312 
1313  add_var(identifier);
1314 
1315  const exprt v_expr=
1316  symbol_exprt("value_set::" + id2string(function) + "::" +
1317  "argument$"+std::to_string(i), it->type());
1318 
1319  const symbol_exprt actual_lhs(identifier, it->type());
1320  assign(actual_lhs, v_expr, ns);
1321  i++;
1322  }
1323 }
1324 
1326  const exprt &lhs,
1327  const namespacet &ns)
1328 {
1329  if(lhs.is_nil())
1330  return;
1331 
1332  std::string rvs = "value_set::return_value" + std::to_string(from_function);
1333  symbol_exprt rhs(rvs, lhs.type());
1334 
1335  assign(lhs, rhs, ns);
1336 }
1337 
1338 void value_set_fit::apply_code(const codet &code, const namespacet &ns)
1339 {
1340  const irep_idt &statement=code.get(ID_statement);
1341 
1342  if(statement==ID_block)
1343  {
1344  for(const auto &stmt : to_code_block(code).statements())
1345  apply_code(stmt, ns);
1346  }
1347  else if(statement==ID_function_call)
1348  {
1349  // shouldn't be here
1350  UNREACHABLE;
1351  }
1352  else if(statement==ID_assign)
1353  {
1354  if(code.operands().size()!=2)
1355  throw "assignment expected to have two operands";
1356 
1357  assign(code.op0(), code.op1(), ns);
1358  }
1359  else if(statement==ID_decl)
1360  {
1361  if(code.operands().size()!=1)
1362  throw "decl expected to have one operand";
1363 
1364  const exprt &lhs=code.op0();
1365 
1366  if(lhs.id()!=ID_symbol)
1367  throw "decl expected to have symbol on lhs";
1368 
1369  assign(lhs, exprt(ID_invalid, lhs.type()), ns);
1370  }
1371  else if(statement==ID_expression)
1372  {
1373  // can be ignored, we don't expect side effects here
1374  }
1375  else if(statement==ID_cpp_delete ||
1376  statement==ID_cpp_delete_array)
1377  {
1378  // does nothing
1379  }
1380  else if(statement=="lock" || statement=="unlock")
1381  {
1382  // ignore for now
1383  }
1384  else if(statement==ID_asm)
1385  {
1386  // ignore for now, probably not safe
1387  }
1388  else if(statement==ID_nondet)
1389  {
1390  // doesn't do anything
1391  }
1392  else if(statement==ID_printf)
1393  {
1394  // doesn't do anything
1395  }
1396  else if(statement==ID_return)
1397  {
1398  const code_returnt &code_return = to_code_return(code);
1399  // this is turned into an assignment
1400  std::string rvs = "value_set::return_value" + std::to_string(from_function);
1401  symbol_exprt lhs(rvs, code_return.return_value().type());
1402  assign(lhs, code_return.return_value(), ns);
1403  }
1404  else if(statement==ID_fence)
1405  {
1406  }
1407  else if(
1408  statement == ID_array_copy || statement == ID_array_replace ||
1409  statement == ID_array_set || statement == ID_array_equal)
1410  {
1411  }
1413  {
1414  // doesn't do anything
1415  }
1416  else if(statement == ID_havoc_object)
1417  {
1418  }
1419  else
1420  throw
1421  code.pretty()+"\n"+
1422  "value_set_fit: unexpected statement: "+id2string(statement);
1423 }
exprt::copy_to_operands
void copy_to_operands(const exprt &expr)
Copy the given argument to the end of exprt's operands.
Definition: expr.h:155
UNREACHABLE
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:503
struct_union_typet::components
const componentst & components() const
Definition: std_types.h:147
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:36
value_set_fit::get_entry
entryt & get_entry(const idt &id, const std::string &suffix)
Definition: value_set_fi.h:230
alloc_adapter_prefix
static const char * alloc_adapter_prefix
Definition: value_set_fi.cpp:36
format
static format_containert< T > format(const T &o)
Definition: format.h:37
mp_integer
BigInt mp_integer
Definition: smt_terms.h:17
value_set_fit::object_map_dt::begin
iterator begin()
Definition: value_set_fi.h:79
arith_tools.h
value_set_fit::flatten_seent
std::set< idt > flatten_seent
Definition: value_set_fi.h:196
codet::op0
exprt & op0()
Definition: expr.h:125
value_set_fit::offset_is_zero
bool offset_is_zero(const offsett &offset) const
Definition: value_set_fi.h:61
goto_instruction_code.h
to_struct_union_type
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
Definition: std_types.h:214
to_dereference_expr
const dereference_exprt & to_dereference_expr(const exprt &expr)
Cast an exprt to a dereference_exprt.
Definition: pointer_expr.h:716
widen_modet::no
@ no
value_set_fi.h
value_set_fit::object_map_dt::iterator
data_typet::iterator iterator
Definition: value_set_fi.h:73
symbolt::display_name
const irep_idt & display_name() const
Return language specific display name if present.
Definition: symbol.h:55
value_set_fit::values
valuest values
Definition: value_set_fi.h:258
typet
The type of an expression, extends irept.
Definition: type.h:28
code_typet::parameterst
std::vector< parametert > parameterst
Definition: std_types.h:541
irept::pretty
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
Definition: irep.cpp:495
value_set_fit::assign
void assign(const exprt &lhs, const exprt &rhs, const namespacet &ns)
Definition: value_set_fi.cpp:961
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
value_set_fit::get_reference_set_sharing_rec
void get_reference_set_sharing_rec(const exprt &expr, object_mapt &dest, const namespacet &ns) const
Definition: value_set_fi.cpp:761
irept::find
const irept & find(const irep_idt &name) const
Definition: irep.cpp:106
struct_union_typet
Base type for structs and unions.
Definition: std_types.h:61
symbolt::type
typet type
Type of symbol.
Definition: symbol.h:31
dynamic_object_exprt
Representation of heap-allocated objects.
Definition: pointer_expr.h:257
numberingt< exprt, irep_hash >
value_set_fit::expr_sett
std::unordered_set< exprt, irep_hash > expr_sett
Definition: value_set_fi.h:190
object_descriptor_exprt
Split an expression into a base object and a (byte) offset.
Definition: pointer_expr.h:166
prefix.h
value_set_fit::do_function_call
void do_function_call(const irep_idt &function, const exprt::operandst &arguments, const namespacet &ns)
Definition: value_set_fi.cpp:1276
value_set_fit::entryt
Definition: value_set_fi.h:173
to_array_of_expr
const array_of_exprt & to_array_of_expr(const exprt &expr)
Cast an exprt to an array_of_exprt.
Definition: std_expr.h:1543
to_type_with_subtype
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition: type.h:193
value_set_fit::from_function
unsigned from_function
Definition: value_set_fi.h:39
exprt
Base class for all expressions.
Definition: expr.h:55
from_type
std::string from_type(const namespacet &ns, const irep_idt &identifier, const typet &type)
Definition: language_util.cpp:51
value_set_fit::dereference_rec
void dereference_rec(const exprt &src, exprt &dest) const
Definition: value_set_fi.cpp:686
to_string
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.
Definition: string_constraint.cpp:58
type_with_subtypet
Type with a single subtype.
Definition: type.h:164
value_set_fit::from_target_index
unsigned from_target_index
Definition: value_set_fi.h:40
to_side_effect_expr
side_effect_exprt & to_side_effect_expr(exprt &expr)
Definition: std_code.h:1506
value_set_fit::flatten
void flatten(const entryt &e, object_mapt &dest) const
Definition: value_set_fi.cpp:135
symbol_exprt
Expression to hold a symbol (variable)
Definition: std_expr.h:112
namespace.h
value_set_fit::flatten_rec
void flatten_rec(const entryt &, object_mapt &, flatten_seent &) const
Definition: value_set_fi.cpp:151
irept::get
const irep_idt & get(const irep_idt &name) const
Definition: irep.cpp:45
to_binary_expr
const binary_exprt & to_binary_expr(const exprt &expr)
Cast an exprt to a binary_exprt.
Definition: std_expr.h:660
value_set_fit::entryt::suffix
std::string suffix
Definition: value_set_fi.h:177
namespacet
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:90
value_set_fit::entryt::identifier
idt identifier
Definition: value_set_fi.h:176
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
value_set_fit::apply_code
void apply_code(const codet &code, const namespacet &ns)
Definition: value_set_fi.cpp:1338
dynamic_object_exprt::get_instance
unsigned int get_instance() const
Definition: pointer_expr.cpp:23
byte_operators.h
Expression classes for byte-level operators.
to_code_type
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition: std_types.h:744
value_set_fit::changed
bool changed
Definition: value_set_fi.h:260
has_prefix
bool has_prefix(const std::string &s, const std::string &prefix)
Definition: converter.cpp:13
DATA_INVARIANT
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition: invariant.h:510
value_set_fit::object_map_dt::end
iterator end()
Definition: value_set_fi.h:83
id2string
const std::string & id2string(const irep_idt &d)
Definition: irep.h:47
member_exprt::compound
const exprt & compound() const
Definition: std_expr.h:2843
get_identifier
static optionalt< smt_termt > get_identifier(const exprt &expr, const std::unordered_map< exprt, smt_identifier_termt, irep_hash > &expression_handle_identifiers, const std::unordered_map< exprt, smt_identifier_termt, irep_hash > &expression_identifiers)
Definition: smt2_incremental_decision_procedure.cpp:328
forall_operands
#define forall_operands(it, expr)
Definition: expr.h:20
language_util.h
irept::set
void set(const irep_idt &name, const irep_idt &value)
Definition: irep.h:420
value_set_fit::object_map_dt::const_iterator
data_typet::const_iterator const_iterator
Definition: value_set_fi.h:75
PRECONDITION
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
symbol_exprt::get_identifier
const irep_idt & get_identifier() const
Definition: std_expr.h:142
value_set_fit::get_value_set
std::vector< exprt > get_value_set(const exprt &expr, const namespacet &ns) const
Definition: value_set_fi.cpp:294
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
index_exprt::index
exprt & index()
Definition: std_expr.h:1450
irept::get_string
const std::string & get_string(const irep_idt &name) const
Definition: irep.h:409
value_set_fit::assign_rec
void assign_rec(const exprt &lhs, const object_mapt &values_rhs, const std::string &suffix, const namespacet &ns, assign_recursion_sett &recursion_set)
Definition: value_set_fi.cpp:1122
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
code_typet
Base type of functions.
Definition: std_types.h:538
symbol.h
Symbol table entry.
value_set_fit::valuest
std::map< idt, entryt > valuest
Definition: value_set_fi.h:195
irept::is_nil
bool is_nil() const
Definition: irep.h:376
irept::id
const irep_idt & id() const
Definition: irep.h:396
value_set_fit::entryt::object_map
object_mapt object_map
Definition: value_set_fi.h:175
exprt::operandst
std::vector< exprt > operandst
Definition: expr.h:58
dstringt::empty
bool empty() const
Definition: dstring.h:88
unary_exprt::op
const exprt & op() const
Definition: std_expr.h:326
code_typet::parameters
const parameterst & parameters() const
Definition: std_types.h:655
to_dynamic_object_expr
const dynamic_object_exprt & to_dynamic_object_expr(const exprt &expr)
Cast an exprt to a dynamic_object_exprt.
Definition: pointer_expr.h:301
reference_counting< object_map_dt >
std_code.h
value_set_fit::object_map_dt::blank
static const object_map_dt blank
Definition: value_set_fi.h:100
to_with_expr
const with_exprt & to_with_expr(const exprt &expr)
Cast an exprt to a with_exprt.
Definition: std_expr.h:2486
dstringt::clear
void clear()
Definition: dstring.h:158
side_effect_exprt::get_statement
const irep_idt & get_statement() const
Definition: std_code.h:1472
simplify_expr.h
can_cast_expr< code_outputt >
bool can_cast_expr< code_outputt >(const exprt &base)
Definition: goto_instruction_code.h:482
exprt::is_zero
bool is_zero() const
Return whether the expression is a constant representing 0.
Definition: expr.cpp:65
member_exprt
Extract member of struct or union.
Definition: std_expr.h:2793
value_set_fit::make_union
bool make_union(object_mapt &dest, const object_mapt &src) const
Definition: value_set_fi.cpp:280
expr_util.h
Deprecated expression utility functions.
dynamic_object_exprt::set_instance
void set_instance(unsigned int instance)
Definition: pointer_expr.cpp:18
value_set_fit::assign_recursion_sett
std::unordered_set< idt > assign_recursion_sett
Definition: value_set_fi.h:199
value_set_fit::output
void output(const namespacet &ns, std::ostream &out) const
Definition: value_set_fi.cpp:38
dynamic_object_exprt::valid
exprt & valid()
Definition: pointer_expr.h:273
value_set_fit::gvs_recursion_sett
std::unordered_set< idt > gvs_recursion_sett
Definition: value_set_fi.h:197
code_returnt
goto_instruction_codet representation of a "return from a function" statement.
Definition: goto_instruction_code.h:494
value_set_fit::to_expr
exprt to_expr(const object_map_dt::value_type &it) const
Definition: value_set_fi.cpp:221
value_set_fit::do_end_function
void do_end_function(const exprt &lhs, const namespacet &ns)
Definition: value_set_fi.cpp:1325
namespace_baset::follow
const typet & follow(const typet &) const
Resolve type symbol to the type it points to.
Definition: namespace.cpp:49
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
exprt::is_constant
bool is_constant() const
Return whether the expression is a constant.
Definition: expr.cpp:27
value_set_fit::object_numbering
static object_numberingt object_numbering
Definition: value_set_fi.h:41
reference_counting::read
const T & read() const
Definition: reference_counting.h:69
pointer_typet::base_type
const typet & base_type() const
The type of the data what we point to.
Definition: pointer_expr.h:35
to_array_type
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition: std_types.h:844
reference_counting::write
T & write()
Definition: reference_counting.h:76
can_cast_expr< code_inputt >
bool can_cast_expr< code_inputt >(const exprt &base)
Definition: goto_instruction_code.h:436
value_set_fit::function_numbering
static numberingt< irep_idt > function_numbering
Definition: value_set_fi.h:42
type_with_subtypet::subtype
const typet & subtype() const
Definition: type.h:172
to_code_block
const code_blockt & to_code_block(const codet &code)
Definition: std_code.h:203
to_member_expr
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition: std_expr.h:2886
value_set_fit::get_reference_set_sharing
void get_reference_set_sharing(const exprt &expr, expr_sett &expr_set, const namespacet &ns) const
Definition: value_set_fi.cpp:749
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
exprt::operands
operandst & operands()
Definition: expr.h:94
value_set_fit::offsett
optionalt< mp_integer > offsett
Represents the offset into an object: either a unique integer offset, or an unknown value,...
Definition: value_set_fi.h:60
codet::op1
exprt & op1()
Definition: expr.h:128
is_null_pointer
bool is_null_pointer(const constant_exprt &expr)
Returns true if expr has a pointer type and a value NULL; it also returns true when expr has value ze...
Definition: expr_util.cpp:315
index_exprt
Array index operator.
Definition: std_expr.h:1409
address_of_exprt
Operator to return the address of an object.
Definition: pointer_expr.h:370
value_set_fit::object_map_dt::value_type
data_typet::value_type value_type
Definition: value_set_fi.h:77
typecast_exprt
Semantic type conversion.
Definition: std_expr.h:2016
code_returnt::return_value
const exprt & return_value() const
Definition: goto_instruction_code.h:502
object_descriptor_exprt::object
exprt & object()
Definition: pointer_expr.h:193
true_exprt
The Boolean constant true.
Definition: std_expr.h:3007
c_index_type
bitvector_typet c_index_type()
Definition: c_types.cpp:16
to_code_return
const code_returnt & to_code_return(const goto_instruction_codet &code)
Definition: goto_instruction_code.h:537
c_types.h
from_expr
std::string from_expr(const namespacet &ns, const irep_idt &identifier, const exprt &expr)
Definition: language_util.cpp:38
value_set_fit::get_reference_set
void get_reference_set(const exprt &expr, expr_sett &expr_set, const namespacet &ns) const
Definition: value_set_fi.cpp:701
symbolt::name
irep_idt name
The unique identifier.
Definition: symbol.h:40
value_set_fit::object_map_dt
Definition: value_set_fi.h:66
value_set_fit::add_var
void add_var(const idt &id)
Definition: value_set_fi.h:220
value_set_fit::insert
bool insert(object_mapt &dest, const object_map_dt::value_type &it) const
Definition: value_set_fi.h:115
value_set_fit::get_value_set_rec
void get_value_set_rec(const exprt &expr, object_mapt &dest, const std::string &suffix, const typet &original_type, const namespacet &ns, gvs_recursion_sett &recursion_set) const
Definition: value_set_fi.cpp:367
array_typet::element_type
const typet & element_type() const
The type of the elements of the array.
Definition: std_types.h:785
codet
Data structure for representing an arbitrary statement in a program.
Definition: std_code_base.h:28
to_constant_expr
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition: std_expr.h:2992
object_descriptor_exprt::offset
exprt & offset()
Definition: pointer_expr.h:209
integer2string
const std::string integer2string(const mp_integer &n, unsigned base)
Definition: mp_arith.cpp:103