CBMC
string_abstraction.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: String Abstraction
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
11 
12 #include "string_abstraction.h"
13 
14 #include <algorithm>
15 
16 #include <util/arith_tools.h>
17 #include <util/c_types.h>
18 #include <util/expr_util.h>
19 #include <util/fresh_symbol.h>
20 #include <util/message.h>
21 #include <util/pointer_expr.h>
23 #include <util/std_code.h>
24 #include <util/string_constant.h>
25 
26 #include "goto_model.h"
27 #include "pointer_arithmetic.h"
28 
30  const exprt &object,
31  exprt &dest, bool write)
32 {
33  // debugging
34  if(build(object, dest, write))
35  return true;
36 
37  // extra consistency check
38  // use
39  // #define build_wrap(a,b,c) build(a,b,c)
40  // to avoid it
41  const typet &a_t=build_abstraction_type(object.type());
42  /*assert(dest.type() == a_t ||
43  (dest.type().id()==ID_array && a_t.id()==ID_pointer &&
44  dest.type().subtype() == a_t.subtype()));
45  */
46  if(
47  dest.type() != a_t &&
48  !(dest.type().id() == ID_array && a_t.id() == ID_pointer &&
49  to_array_type(dest.type()).element_type() ==
50  to_pointer_type(a_t).base_type()))
51  {
53  log.warning() << "warning: inconsistent abstract type for "
54  << object.pretty() << messaget::eom;
55  return true;
56  }
57 
58  return false;
59 }
60 
62 {
63  return type.id() == ID_pointer &&
65 }
66 
67 static inline bool is_ptr_argument(const typet &type)
68 {
69  return type.id()==ID_pointer;
70 }
71 
73  goto_modelt &goto_model,
74  message_handlert &message_handler)
75 {
76  string_abstractiont{goto_model, message_handler}.apply();
77 }
78 
80  goto_modelt &goto_model,
81  message_handlert &_message_handler)
82  : sym_suffix("#str$fcn"),
83  goto_model(goto_model),
84  ns(goto_model.symbol_table),
85  temporary_counter(0),
86  message_handler(_message_handler)
87 {
88  struct_typet s({{"is_zero", build_type(whatt::IS_ZERO)},
89  {"length", build_type(whatt::LENGTH)},
90  {"size", build_type(whatt::SIZE)}});
91  s.components()[0].set_pretty_name("is_zero");
92  s.components()[1].set_pretty_name("length");
93  s.components()[2].set_pretty_name("size");
94 
95  symbolt &struct_symbol = get_fresh_aux_symbol(
96  s,
97  "tag-",
98  "string_struct",
100  ID_C,
101  ns,
103  struct_symbol.is_type = true;
104  struct_symbol.is_lvalue = false;
105  struct_symbol.is_state_var = false;
106  struct_symbol.is_thread_local = true;
107  struct_symbol.is_file_local = true;
108  struct_symbol.is_auxiliary = false;
109  struct_symbol.is_macro = true;
110 
111  string_struct = struct_tag_typet{struct_symbol.name};
112 }
113 
115 {
116  typet type;
117 
118  // clang-format off
119  switch(what)
120  {
121  case whatt::IS_ZERO: type=c_bool_type(); break;
122  case whatt::LENGTH: type=size_type(); break;
123  case whatt::SIZE: type=size_type(); break;
124  }
125  // clang-format on
126 
127  return type;
128 }
129 
131 {
133  symbol_tablet &symbol_table = goto_model.symbol_table;
134 
135  // iterate over all previously known symbols as the body of the loop modifies
136  // the symbol table and can thus invalidate iterators
137  for(auto &sym_name : symbol_table.sorted_symbol_names())
138  {
139  symbolt &symbol = symbol_table.get_writeable_ref(sym_name);
140  const typet &type = symbol.type;
141 
142  if(type.id() != ID_code)
143  continue;
144 
145  sym_suffix = "#str$" + id2string(sym_name);
146 
147  goto_functionst::function_mapt::iterator fct_entry =
148  dest.function_map.find(sym_name);
149  if(fct_entry != dest.function_map.end())
150  {
151  add_str_parameters(symbol, fct_entry->second.parameter_identifiers);
152  }
153  else
154  {
156  to_code_type(type).parameters().size(), irep_idt{});
157  add_str_parameters(symbol, dummy);
158  }
159  }
160 
161  for(auto &gf_entry : dest.function_map)
162  {
163  sym_suffix = "#str$" + id2string(gf_entry.first);
164  abstract(gf_entry.second.body);
165  }
166 
167  // do we have a main?
168  goto_functionst::function_mapt::iterator
169  m_it=dest.function_map.find(dest.entry_point());
170 
171  if(m_it!=dest.function_map.end())
172  {
173  goto_programt &main=m_it->second.body;
174 
175  // do initialization
177  main.swap(initialization);
179  }
180 }
181 
183 {
184  abstract(dest);
185 
186  // do initialization
188  dest.swap(initialization);
190 }
191 
193  symbolt &fct_symbol,
194  goto_functiont::parameter_identifierst &parameter_identifiers)
195 {
196  code_typet &fct_type = to_code_type(fct_symbol.type);
197  PRECONDITION(fct_type.parameters().size() == parameter_identifiers.size());
198 
199  code_typet::parameterst str_args;
200 
201  goto_functiont::parameter_identifierst::const_iterator param_id_it =
202  parameter_identifiers.begin();
203  for(const auto &parameter : fct_type.parameters())
204  {
205  const typet &abstract_type = build_abstraction_type(parameter.type());
206  if(abstract_type.is_nil())
207  continue;
208 
209  str_args.push_back(add_parameter(fct_symbol, abstract_type, *param_id_it));
210  ++param_id_it;
211  }
212 
213  for(const auto &new_param : str_args)
214  parameter_identifiers.push_back(new_param.get_identifier());
215  fct_type.parameters().insert(
216  fct_type.parameters().end(), str_args.begin(), str_args.end());
217 }
218 
220  const symbolt &fct_symbol,
221  const typet &type,
222  const irep_idt &identifier)
223 {
224  typet final_type=is_ptr_argument(type)?
225  type:pointer_type(type);
226 
227  symbolt &param_symbol = get_fresh_aux_symbol(
228  final_type,
229  id2string(identifier.empty() ? fct_symbol.name : identifier),
230  id2string(
231  identifier.empty() ? fct_symbol.base_name
232  : ns.lookup(identifier).base_name) +
233  "#str",
234  fct_symbol.location,
235  fct_symbol.mode,
237  param_symbol.is_parameter = true;
238  param_symbol.value.make_nil();
239 
240  code_typet::parametert str_parameter{final_type};
241  str_parameter.add_source_location() = fct_symbol.location;
242  str_parameter.set_base_name(param_symbol.base_name);
243  str_parameter.set_identifier(param_symbol.name);
244 
245  if(!identifier.empty())
246  parameter_map.insert(std::make_pair(identifier, param_symbol.name));
247 
248  return str_parameter;
249 }
250 
252 {
253  locals.clear();
254 
256  it=abstract(dest, it);
257 
258  if(locals.empty())
259  return;
260 
261  // go over it again for the newly added locals
262  declare_define_locals(dest);
263  locals.clear();
264 }
265 
267 {
268  typedef std::unordered_map<irep_idt, goto_programt::targett> available_declst;
269  available_declst available_decls;
270 
272  if(it->is_decl())
273  // same name may exist several times due to inlining, make sure the first
274  // declaration is used
275  available_decls.insert(
276  std::make_pair(it->decl_symbol().get_identifier(), it));
277 
278  // declare (and, if necessary, define) locals
279  for(const auto &l : locals)
280  {
281  goto_programt::targett ref_instr=dest.instructions.begin();
282  bool has_decl=false;
283 
284  available_declst::const_iterator entry=available_decls.find(l.first);
285 
286  if(available_declst::const_iterator(available_decls.end())!=entry)
287  {
288  ref_instr=entry->second;
289  has_decl=true;
290  }
291 
292  goto_programt tmp;
293  make_decl_and_def(tmp, ref_instr, l.second, l.first);
294 
295  if(has_decl)
296  ++ref_instr;
297  dest.insert_before_swap(ref_instr, tmp);
298  }
299 }
300 
302  goto_programt::targett ref_instr,
303  const irep_idt &identifier,
304  const irep_idt &source_sym)
305 {
306  const symbolt &symbol=ns.lookup(identifier);
307  symbol_exprt sym_expr=symbol.symbol_expr();
308  code_declt decl{sym_expr};
309  decl.add_source_location() = ref_instr->source_location();
310  dest.add(
311  goto_programt::make_decl(std::move(decl), ref_instr->source_location()));
312 
313  exprt val=symbol.value;
314  // initialize pointers with suitable objects
315  if(val.is_nil())
316  {
317  const symbolt &orig=ns.lookup(source_sym);
318  val = make_val_or_dummy_rec(dest, ref_instr, symbol, orig.type);
319  }
320 
321  // may still be nil (structs, then assignments have been done already)
322  if(val.is_not_nil())
323  {
324  code_assignt assignment{sym_expr, val, ref_instr->source_location()};
325  dest.add(
326  goto_programt::make_assignment(assignment, ref_instr->source_location()));
327  }
328 }
329 
331  goto_programt::targett ref_instr,
332  const symbolt &symbol, const typet &source_type)
333 {
334  if(symbol.type.id() == ID_array || symbol.type.id() == ID_pointer)
335  {
336  const typet &source_subt = is_ptr_string_struct(symbol.type)
337  ? source_type
338  : to_type_with_subtype(source_type).subtype();
340  dest,
341  ref_instr,
342  symbol,
343  irep_idt(),
345  source_subt);
346 
347  if(symbol.type.id() == ID_array)
348  return array_of_exprt(sym_expr, to_array_type(symbol.type));
349  else
350  return address_of_exprt(sym_expr);
351  }
352  else if(
353  symbol.type.id() == ID_union_tag ||
354  (symbol.type.id() == ID_struct_tag && symbol.type != string_struct))
355  {
356  const struct_union_typet::componentst &s_components =
358  const struct_union_typet::componentst &components =
360  unsigned seen=0;
361 
362  struct_union_typet::componentst::const_iterator it2=components.begin();
363  for(struct_union_typet::componentst::const_iterator
364  it=s_components.begin();
365  it!=s_components.end() && it2!=components.end();
366  ++it)
367  {
368  if(it->get_name()!=it2->get_name())
369  continue;
370 
371  if(
372  it2->type().id() == ID_pointer || it2->type().id() == ID_array ||
373  it2->type().id() == ID_struct_tag || it2->type().id() == ID_union_tag)
374  {
376  dest, ref_instr, symbol, it2->get_name(), it2->type(), it->type());
377 
378  member_exprt member(symbol.symbol_expr(), it2->get_name(), it2->type());
379 
380  code_assignt assignment{member, sym_expr, ref_instr->source_location()};
382  code_assignt(member, sym_expr), ref_instr->source_location()));
383  }
384 
385  ++seen;
386  ++it2;
387  }
388 
389  INVARIANT(
390  components.size() == seen,
391  "some of the symbol's component names were not found in the source");
392  }
393 
394  return nil_exprt();
395 }
396 
398  goto_programt &dest,
399  goto_programt::targett ref_instr,
400  const symbolt &symbol,
401  const irep_idt &component_name,
402  const typet &type,
403  const typet &source_type)
404 {
405  std::string suffix="$strdummy";
406  if(!component_name.empty())
407  suffix="#"+id2string(component_name)+suffix;
408 
409  irep_idt dummy_identifier=id2string(symbol.name)+suffix;
410 
411  auxiliary_symbolt new_symbol;
412  new_symbol.type=type;
413  new_symbol.value.make_nil();
414  new_symbol.location = ref_instr->source_location();
415  new_symbol.name=dummy_identifier;
416  new_symbol.module=symbol.module;
417  new_symbol.base_name=id2string(symbol.base_name)+suffix;
418  new_symbol.mode=symbol.mode;
419  new_symbol.pretty_name=id2string(
420  symbol.pretty_name.empty()?symbol.base_name:symbol.pretty_name)+suffix;
421 
422  symbol_exprt sym_expr=new_symbol.symbol_expr();
423 
424  // make sure it is declared before the recursive call
425  code_declt decl{sym_expr};
426  decl.add_source_location() = ref_instr->source_location();
427  dest.add(
428  goto_programt::make_decl(std::move(decl), ref_instr->source_location()));
429 
430  // set the value - may be nil
431  if(
432  source_type.id() == ID_array &&
433  is_char_type(to_array_type(source_type).element_type()) &&
434  type == string_struct)
435  {
436  new_symbol.value = struct_exprt(
437  {build_unknown(whatt::IS_ZERO, false),
439  to_array_type(source_type).size().id() == ID_infinity
440  ? build_unknown(whatt::SIZE, false)
442  to_array_type(source_type).size(), build_type(whatt::SIZE))},
443  string_struct);
444  }
445  else
446  new_symbol.value=
447  make_val_or_dummy_rec(dest, ref_instr, new_symbol, source_type);
448 
449  if(new_symbol.value.is_not_nil())
450  {
451  code_assignt assignment{
452  sym_expr, new_symbol.value, ref_instr->source_location()};
453  dest.add(
454  goto_programt::make_assignment(assignment, ref_instr->source_location()));
455  }
456 
457  goto_model.symbol_table.insert(std::move(new_symbol));
458 
459  return sym_expr;
460 }
461 
463  goto_programt &dest,
465 {
466  switch(it->type())
467  {
468  case ASSIGN:
469  it=abstract_assign(dest, it);
470  break;
471 
472  case GOTO:
473  case ASSERT:
474  case ASSUME:
475  if(has_string_macros(it->condition()))
477  it->condition_nonconst(), false, it->source_location());
478  break;
479 
480  case FUNCTION_CALL:
482  break;
483 
484  case SET_RETURN_VALUE:
485  // use remove_returns
486  UNREACHABLE;
487  break;
488 
489  case END_FUNCTION:
490  case START_THREAD:
491  case END_THREAD:
492  case ATOMIC_BEGIN:
493  case ATOMIC_END:
494  case DECL:
495  case DEAD:
496  case CATCH:
497  case THROW:
498  case SKIP:
499  case OTHER:
500  case LOCATION:
501  break;
502 
503  case INCOMPLETE_GOTO:
504  case NO_INSTRUCTION_TYPE:
505  UNREACHABLE;
506  break;
507  }
508 
509  return it;
510 }
511 
513  goto_programt &dest,
514  goto_programt::targett target)
515 {
516  {
517  exprt &lhs = target->assign_lhs_nonconst();
518  exprt &rhs = target->assign_rhs_nonconst();
519 
520  if(has_string_macros(lhs))
521  {
522  replace_string_macros(lhs, true, target->source_location());
523  move_lhs_arithmetic(lhs, rhs);
524  }
525 
526  if(has_string_macros(rhs))
527  replace_string_macros(rhs, false, target->source_location());
528  }
529 
530  const typet &type = target->assign_lhs().type();
531 
532  if(type.id() == ID_pointer || type.id() == ID_array)
533  return abstract_pointer_assign(dest, target);
534  else if(is_char_type(type))
535  return abstract_char_assign(dest, target);
536 
537  return target;
538 }
539 
541  goto_programt::targett target)
542 {
543  auto arguments = as_const(*target).call_arguments();
545 
546  for(const auto &arg : arguments)
547  {
548  const typet &abstract_type = build_abstraction_type(arg.type());
549  if(abstract_type.is_nil())
550  continue;
551 
552  str_args.push_back(exprt());
553  // if function takes void*, build for `arg` will fail if actual parameter
554  // is of some other pointer type; then just introduce an unknown
555  if(build_wrap(arg, str_args.back(), false))
556  str_args.back()=build_unknown(abstract_type, false);
557  // array -> pointer translation
558  if(str_args.back().type().id()==ID_array &&
559  abstract_type.id()==ID_pointer)
560  {
561  INVARIANT(
562  to_array_type(str_args.back().type()).element_type() ==
563  to_pointer_type(abstract_type).base_type(),
564  "argument array type differs from formal parameter pointer type");
565 
566  index_exprt idx(str_args.back(), from_integer(0, c_index_type()));
567  str_args.back()=address_of_exprt(idx);
568  }
569 
570  if(!is_ptr_argument(abstract_type))
571  str_args.back()=address_of_exprt(str_args.back());
572  }
573 
574  if(!str_args.empty())
575  {
576  arguments.insert(arguments.end(), str_args.begin(), str_args.end());
577 
578  auto &parameters =
579  to_code_type(target->call_function().type()).parameters();
580  for(const auto &arg : str_args)
581  parameters.push_back(code_typet::parametert{arg.type()});
582 
583  target->call_arguments() = std::move(arguments);
584  }
585 }
586 
588 {
589  if(expr.id()=="is_zero_string" ||
590  expr.id()=="zero_string_length" ||
591  expr.id()=="buffer_size")
592  return true;
593 
594  for(const auto &op : expr.operands())
595  {
596  if(has_string_macros(op))
597  return true;
598  }
599 
600  return false;
601 }
602 
604  exprt &expr,
605  bool lhs,
606  const source_locationt &source_location)
607 {
608  if(expr.id()=="is_zero_string")
609  {
610  PRECONDITION(expr.operands().size() == 1);
611  exprt tmp =
612  build(to_unary_expr(expr).op(), whatt::IS_ZERO, lhs, source_location);
613  expr.swap(tmp);
614  }
615  else if(expr.id()=="zero_string_length")
616  {
617  PRECONDITION(expr.operands().size() == 1);
618  exprt tmp =
619  build(to_unary_expr(expr).op(), whatt::LENGTH, lhs, source_location);
620  expr.swap(tmp);
621  }
622  else if(expr.id()=="buffer_size")
623  {
624  PRECONDITION(expr.operands().size() == 1);
625  exprt tmp =
626  build(to_unary_expr(expr).op(), whatt::SIZE, false, source_location);
627  expr.swap(tmp);
628  }
629  else
630  Forall_operands(it, expr)
631  replace_string_macros(*it, lhs, source_location);
632 }
633 
635  const exprt &pointer,
636  whatt what,
637  bool write,
638  const source_locationt &source_location)
639 {
640  // take care of pointer typecasts now
641  if(pointer.id()==ID_typecast)
642  {
643  const exprt &op = to_typecast_expr(pointer).op();
644 
645  // cast from another pointer type?
646  if(
647  op.type().id() != ID_pointer ||
649  {
650  return build_unknown(what, write);
651  }
652 
653  // recursive call
654  return build(op, what, write, source_location);
655  }
656 
657  exprt str_struct;
658  if(build_wrap(pointer, str_struct, write))
659  UNREACHABLE;
660 
661  exprt result=member(str_struct, what);
662 
663  if(what==whatt::LENGTH || what==whatt::SIZE)
664  {
665  // adjust for offset
666  exprt offset = pointer_offset(pointer);
667  typet result_type = result.type();
669  minus_exprt(
670  typecast_exprt::conditional_cast(result, offset.type()), offset),
671  result_type);
672  }
673 
674  return result;
675 }
676 
678 {
679  abstraction_types_mapt::const_iterator map_entry =
680  abstraction_types_map.find(type);
681  if(map_entry!=abstraction_types_map.end())
682  return map_entry->second;
683 
685  tmp.swap(abstraction_types_map);
686  build_abstraction_type_rec(type, tmp);
687 
688  abstraction_types_map.swap(tmp);
689  abstraction_types_map.insert(tmp.begin(), tmp.end());
690  map_entry = abstraction_types_map.find(type);
691  CHECK_RETURN(map_entry != abstraction_types_map.end());
692  return map_entry->second;
693 }
694 
696  const abstraction_types_mapt &known)
697 {
698  abstraction_types_mapt::const_iterator known_entry = known.find(type);
699  if(known_entry!=known.end())
700  return known_entry->second;
701 
702  ::std::pair<abstraction_types_mapt::iterator, bool> map_entry(
703  abstraction_types_map.insert(::std::make_pair(type, typet{ID_nil})));
704  if(!map_entry.second)
705  return map_entry.first->second;
706 
707  if(type.id() == ID_array || type.id() == ID_pointer)
708  {
709  // char* or void* or char[]
710  if(
711  is_char_type(to_type_with_subtype(type).subtype()) ||
712  to_type_with_subtype(type).subtype().id() == ID_empty)
713  map_entry.first->second=pointer_type(string_struct);
714  else
715  {
716  const typet &subt =
717  build_abstraction_type_rec(to_type_with_subtype(type).subtype(), known);
718  if(!subt.is_nil())
719  {
720  if(type.id() == ID_array)
721  map_entry.first->second =
722  array_typet(subt, to_array_type(type).size());
723  else
724  map_entry.first->second=pointer_type(subt);
725  }
726  }
727  }
728  else if(type.id() == ID_struct_tag || type.id() == ID_union_tag)
729  {
730  const struct_union_typet &struct_union_type =
731  type.id() == ID_struct_tag ? static_cast<const struct_union_typet &>(
733  : static_cast<const struct_union_typet &>(
735 
737  for(const auto &comp : struct_union_type.components())
738  {
739  if(comp.get_anonymous())
740  continue;
741  typet subt=build_abstraction_type_rec(comp.type(), known);
742  if(subt.is_nil())
743  // also precludes structs with pointers to the same datatype
744  continue;
745 
746  new_comp.push_back(struct_union_typet::componentt());
747  new_comp.back().set_name(comp.get_name());
748  new_comp.back().set_pretty_name(comp.get_pretty_name());
749  new_comp.back().type()=subt;
750  }
751  if(!new_comp.empty())
752  {
753  struct_union_typet abstracted_type = struct_union_type;
754  abstracted_type.components().swap(new_comp);
755 
756  const symbolt &existing_tag_symbol =
757  ns.lookup(to_tag_type(type).get_identifier());
758  symbolt &abstracted_type_symbol = get_fresh_aux_symbol(
759  abstracted_type,
760  "",
761  id2string(existing_tag_symbol.name),
762  existing_tag_symbol.location,
763  existing_tag_symbol.mode,
764  ns,
766  abstracted_type_symbol.is_type = true;
767  abstracted_type_symbol.is_lvalue = false;
768  abstracted_type_symbol.is_state_var = false;
769  abstracted_type_symbol.is_thread_local = true;
770  abstracted_type_symbol.is_file_local = true;
771  abstracted_type_symbol.is_auxiliary = false;
772  abstracted_type_symbol.is_macro = true;
773 
774  if(type.id() == ID_struct_tag)
775  map_entry.first->second = struct_tag_typet{abstracted_type_symbol.name};
776  else
777  map_entry.first->second = union_tag_typet{abstracted_type_symbol.name};
778  }
779  }
780 
781  return map_entry.first->second;
782 }
783 
784 bool string_abstractiont::build(const exprt &object, exprt &dest, bool write)
785 {
786  const typet &abstract_type=build_abstraction_type(object.type());
787  if(abstract_type.is_nil())
788  return true;
789 
790  if(object.id()==ID_typecast)
791  {
792  if(build(to_typecast_expr(object).op(), dest, write))
793  return true;
794 
795  return dest.type() != abstract_type ||
796  (dest.type().id() == ID_array && abstract_type.id() == ID_pointer &&
797  to_array_type(dest.type()).element_type() ==
798  to_pointer_type(abstract_type).base_type());
799  }
800 
801  if(object.id()==ID_string_constant)
802  {
803  const std::string &str_value =
804  id2string(to_string_constant(object).value());
805  // make sure we handle the case of a string constant with string-terminating
806  // \0 in it
807  const std::size_t str_len =
808  std::min(str_value.size(), str_value.find('\0'));
809  return build_symbol_constant(str_len, str_len+1, dest);
810  }
811 
812  if(
813  object.id() == ID_array &&
814  is_char_type(to_array_type(object.type()).element_type()))
815  return build_array(to_array_expr(object), dest, write);
816 
817  // other constants aren't useful
818  if(object.is_constant())
819  return true;
820 
821  if(object.id()==ID_symbol)
822  return build_symbol(to_symbol_expr(object), dest);
823 
824  if(object.id()==ID_if)
825  return build_if(to_if_expr(object), dest, write);
826 
827  if(object.id()==ID_member)
828  {
829  const member_exprt &o_mem=to_member_expr(object);
830  exprt compound;
831  if(build_wrap(o_mem.struct_op(), compound, write))
832  return true;
833  dest = member_exprt{
834  std::move(compound), o_mem.get_component_name(), abstract_type};
835  return false;
836  }
837 
838  if(object.id()==ID_dereference)
839  {
840  const dereference_exprt &o_deref=to_dereference_expr(object);
841  exprt pointer;
842  if(build_wrap(o_deref.pointer(), pointer, write))
843  return true;
844  dest = dereference_exprt{std::move(pointer)};
845  return false;
846  }
847 
848  if(object.id()==ID_index)
849  {
850  const index_exprt &o_index=to_index_expr(object);
851  exprt array;
852  if(build_wrap(o_index.array(), array, write))
853  return true;
854  dest = index_exprt{std::move(array), o_index.index()};
855  return false;
856  }
857 
858  // handle pointer stuff
859  if(object.type().id()==ID_pointer)
860  return build_pointer(object, dest, write);
861 
862  return true;
863 }
864 
866  exprt &dest, bool write)
867 {
868  if_exprt new_if(o_if.cond(), exprt(), exprt());
869 
870  // recursive calls
871  bool op1_err=build_wrap(o_if.true_case(), new_if.true_case(), write);
872  bool op2_err=build_wrap(o_if.false_case(), new_if.false_case(), write);
873  if(op1_err && op2_err)
874  return true;
875  // at least one of them gave proper results
876  if(op1_err)
877  {
878  new_if.type()=new_if.false_case().type();
879  new_if.true_case()=build_unknown(new_if.type(), write);
880  }
881  else if(op2_err)
882  {
883  new_if.type()=new_if.true_case().type();
884  new_if.false_case()=build_unknown(new_if.type(), write);
885  }
886  else
887  new_if.type()=new_if.true_case().type();
888 
889  dest.swap(new_if);
890  return false;
891 }
892 
894  exprt &dest, bool write)
895 {
896  PRECONDITION(is_char_type(object.type().element_type()));
897 
898  // writing is invalid
899  if(write)
900  return true;
901 
902  const exprt &a_size=to_array_type(object.type()).size();
903  const auto size = numeric_cast<mp_integer>(a_size);
904  // don't do anything, if we cannot determine the size
905  if(!size.has_value())
906  return true;
907  INVARIANT(
908  *size == object.operands().size(),
909  "wrong number of array object arguments");
910 
911  exprt::operandst::const_iterator it=object.operands().begin();
912  for(mp_integer i = 0; i < *size; ++i, ++it)
913  if(it->is_zero())
914  return build_symbol_constant(i, *size, dest);
915 
916  return true;
917 }
918 
920  exprt &dest, bool write)
921 {
922  PRECONDITION(object.type().id() == ID_pointer);
923 
924  pointer_arithmetict ptr(object);
925  if(ptr.pointer.id()==ID_address_of)
926  {
928 
929  if(a.object().id()==ID_index)
930  return build_wrap(to_index_expr(a.object()).array(), dest, write);
931 
932  // writing is invalid
933  if(write)
934  return true;
935 
936  if(build_wrap(a.object(), dest, write))
937  return true;
938  dest=address_of_exprt(dest);
939  return false;
940  }
941  else if(
942  ptr.pointer.id() == ID_symbol &&
943  is_char_type(to_pointer_type(object.type()).base_type()))
944  // recursive call; offset will be handled by pointer_offset in SIZE/LENGTH
945  // checks
946  return build_wrap(ptr.pointer, dest, write);
947 
948  // we don't handle other pointer arithmetic
949  return true;
950 }
951 
953 {
954  typet type=build_type(what);
955 
956  if(write)
957  return exprt(ID_null_object, type);
958 
959  exprt result;
960 
961  switch(what)
962  {
963  case whatt::IS_ZERO:
964  result = from_integer(0, type);
965  break;
966 
967  case whatt::LENGTH:
968  case whatt::SIZE:
969  result = side_effect_expr_nondett(type, source_locationt());
970  break;
971  }
972 
973  return result;
974 }
975 
977 {
978  if(write)
979  return exprt(ID_null_object, type);
980 
981  // create an uninitialized dummy symbol
982  // because of a lack of contextual information we can't build a nice name
983  // here, but moving that into locals should suffice for proper operation
984  irep_idt identifier=
985  "$tmp::nondet_str#str$"+std::to_string(++temporary_counter);
986  // ensure decl and initialization
987  locals[identifier]=identifier;
988 
989  auxiliary_symbolt new_symbol;
990  new_symbol.type=type;
991  new_symbol.value.make_nil();
992  new_symbol.name=identifier;
993  new_symbol.module="$tmp";
994  new_symbol.base_name=identifier;
995  new_symbol.mode=ID_C;
996  new_symbol.pretty_name=identifier;
997 
998  goto_model.symbol_table.insert(std::move(new_symbol));
999 
1000  return ns.lookup(identifier).symbol_expr();
1001 }
1002 
1004 {
1005  const symbolt &symbol=ns.lookup(sym.get_identifier());
1006 
1007  const typet &abstract_type=build_abstraction_type(symbol.type);
1008  CHECK_RETURN(!abstract_type.is_nil());
1009 
1010  irep_idt identifier;
1011 
1012  if(symbol.is_parameter)
1013  {
1014  const auto parameter_map_entry = parameter_map.find(symbol.name);
1015  if(parameter_map_entry == parameter_map.end())
1016  return true;
1017  identifier = parameter_map_entry->second;
1018  }
1019  else if(symbol.is_static_lifetime)
1020  {
1021  std::string sym_suffix_before = sym_suffix;
1022  sym_suffix = "#str";
1023  identifier = id2string(symbol.name) + sym_suffix;
1024  if(!goto_model.symbol_table.has_symbol(identifier))
1025  build_new_symbol(symbol, identifier, abstract_type);
1026  sym_suffix = sym_suffix_before;
1027  }
1028  else
1029  {
1030  identifier=id2string(symbol.name)+sym_suffix;
1031  if(!goto_model.symbol_table.has_symbol(identifier))
1032  build_new_symbol(symbol, identifier, abstract_type);
1033  }
1034 
1035  const symbolt &str_symbol=ns.lookup(identifier);
1036  dest=str_symbol.symbol_expr();
1037  if(symbol.is_parameter && !is_ptr_argument(abstract_type))
1038  dest = dereference_exprt{dest};
1039 
1040  return false;
1041 }
1042 
1044  const irep_idt &identifier, const typet &type)
1045 {
1046  if(!symbol.is_static_lifetime)
1047  locals[symbol.name]=identifier;
1048 
1049  auxiliary_symbolt new_symbol;
1050  new_symbol.type=type;
1051  new_symbol.value.make_nil();
1052  new_symbol.location=symbol.location;
1053  new_symbol.name=identifier;
1054  new_symbol.module=symbol.module;
1055  new_symbol.base_name=id2string(symbol.base_name)+sym_suffix;
1056  new_symbol.mode=symbol.mode;
1057  new_symbol.pretty_name=
1058  id2string(symbol.pretty_name.empty()?symbol.base_name:symbol.pretty_name)+
1059  sym_suffix;
1060  new_symbol.is_static_lifetime=symbol.is_static_lifetime;
1061  new_symbol.is_thread_local=symbol.is_thread_local;
1062 
1063  goto_model.symbol_table.insert(std::move(new_symbol));
1064 
1065  if(symbol.is_static_lifetime)
1066  {
1067  goto_programt::targett dummy_loc =
1069  codet{ID_nil},
1070  symbol.location,
1072  {},
1073  {}});
1074  make_decl_and_def(initialization, dummy_loc, identifier, symbol.name);
1075  initialization.instructions.erase(dummy_loc);
1076  }
1077 }
1078 
1080  const mp_integer &zero_length,
1081  const mp_integer &buf_size,
1082  exprt &dest)
1083 {
1084  irep_idt base="$string_constant_str_"+integer2string(zero_length)
1085  +"_"+integer2string(buf_size);
1086  irep_idt identifier="string_abstraction::"+id2string(base);
1087 
1088  if(!goto_model.symbol_table.has_symbol(identifier))
1089  {
1090  auxiliary_symbolt new_symbol;
1091  new_symbol.type=string_struct;
1092  new_symbol.value.make_nil();
1093  new_symbol.name=identifier;
1094  new_symbol.base_name=base;
1095  new_symbol.mode=ID_C;
1096  new_symbol.pretty_name=base;
1097  new_symbol.is_static_lifetime=true;
1098  new_symbol.is_thread_local=false;
1099  new_symbol.is_file_local=false;
1100 
1101  {
1102  struct_exprt value(
1104  from_integer(zero_length, build_type(whatt::LENGTH)),
1105  from_integer(buf_size, build_type(whatt::SIZE))},
1106  string_struct);
1107 
1108  // initialization
1110  code_assignt(new_symbol.symbol_expr(), value)));
1111  }
1112 
1113  goto_model.symbol_table.insert(std::move(new_symbol));
1114  }
1115 
1116  dest=address_of_exprt(symbol_exprt(identifier, string_struct));
1117 
1118  return false;
1119 }
1120 
1122 {
1123  while(lhs.id() == ID_typecast)
1124  {
1125  typecast_exprt lhs_tc = to_typecast_expr(lhs);
1126  rhs = typecast_exprt::conditional_cast(rhs, lhs_tc.op().type());
1127  lhs.swap(lhs_tc.op());
1128  }
1129 
1130  if(lhs.id()==ID_minus)
1131  {
1132  // move op1 to rhs
1133  exprt rest = to_minus_expr(lhs).op0();
1134  rhs = plus_exprt(rhs, to_minus_expr(lhs).op1());
1135  rhs.type()=lhs.type();
1136  lhs=rest;
1137  }
1138 
1139  while(lhs.id() == ID_typecast)
1140  {
1141  typecast_exprt lhs_tc = to_typecast_expr(lhs);
1142  rhs = typecast_exprt::conditional_cast(rhs, lhs_tc.op().type());
1143  lhs.swap(lhs_tc.op());
1144  }
1145 }
1146 
1148  goto_programt &dest,
1149  const goto_programt::targett target)
1150 {
1151  const exprt &lhs = target->assign_lhs();
1152  const exprt rhs = target->assign_rhs();
1153  const exprt *rhsp = &(target->assign_rhs());
1154 
1155  while(rhsp->id()==ID_typecast)
1156  rhsp = &(to_typecast_expr(*rhsp).op());
1157 
1158  const typet &abstract_type=build_abstraction_type(lhs.type());
1159  if(abstract_type.is_nil())
1160  return target;
1161 
1162  exprt new_lhs, new_rhs;
1163  if(build_wrap(lhs, new_lhs, true))
1164  return target;
1165 
1166  bool unknown=(abstract_type!=build_abstraction_type(rhsp->type()) ||
1167  build_wrap(rhs, new_rhs, false));
1168  if(unknown)
1169  new_rhs=build_unknown(abstract_type, false);
1170 
1171  if(lhs.type().id()==ID_pointer && !unknown)
1172  {
1174  code_assignt(new_lhs, new_rhs, target->source_location()),
1175  target->source_location());
1176  dest.insert_before_swap(target, assignment);
1177 
1178  return std::next(target);
1179  }
1180  else
1181  {
1182  return value_assignments(dest, target, new_lhs, new_rhs);
1183  }
1184 }
1185 
1187  goto_programt &dest,
1188  goto_programt::targett target)
1189 {
1190  const exprt &lhs = target->assign_lhs();
1191  const exprt *rhsp = &(target->assign_rhs());
1192 
1193  while(rhsp->id()==ID_typecast)
1194  rhsp = &(to_typecast_expr(*rhsp).op());
1195 
1196  // we only care if the constant zero is assigned
1197  if(!rhsp->is_zero())
1198  return target;
1199 
1200  // index into a character array
1201  if(lhs.id()==ID_index)
1202  {
1203  const index_exprt &i_lhs=to_index_expr(lhs);
1204 
1205  exprt new_lhs;
1206  if(!build_wrap(i_lhs.array(), new_lhs, true))
1207  {
1208  exprt i2=member(new_lhs, whatt::LENGTH);
1209  INVARIANT(
1210  i2.is_not_nil(),
1211  "failed to create length-component for the left-hand-side");
1212 
1213  exprt new_length =
1215 
1216  if_exprt min_expr(binary_relation_exprt(new_length, ID_lt, i2),
1217  new_length, i2);
1218 
1219  return char_assign(dest, target, new_lhs, i2, min_expr);
1220  }
1221  }
1222  else if(lhs.id()==ID_dereference)
1223  {
1224  pointer_arithmetict ptr(to_dereference_expr(lhs).pointer());
1225  exprt new_lhs;
1226  if(!build_wrap(ptr.pointer, new_lhs, true))
1227  {
1228  const exprt i2=member(new_lhs, whatt::LENGTH);
1229  INVARIANT(
1230  i2.is_not_nil(),
1231  "failed to create length-component for the left-hand-side");
1232 
1233  return char_assign(
1234  dest,
1235  target,
1236  new_lhs,
1237  i2,
1241  }
1242  }
1243 
1244  return target;
1245 }
1246 
1248  goto_programt &dest,
1249  goto_programt::targett target,
1250  const exprt &new_lhs,
1251  const exprt &lhs,
1252  const exprt &rhs)
1253 {
1254  goto_programt tmp;
1255 
1256  const exprt i1=member(new_lhs, whatt::IS_ZERO);
1257  INVARIANT(
1258  i1.is_not_nil(),
1259  "failed to create is_zero-component for the left-hand-side");
1260 
1262  code_assignt(i1, from_integer(1, i1.type()), target->source_location()),
1263  target->source_location()));
1264 
1265  code_assignt assignment{lhs, rhs, target->source_location()};
1266  move_lhs_arithmetic(assignment.lhs(), assignment.rhs());
1267  tmp.add(
1268  goto_programt::make_assignment(assignment, target->source_location()));
1269 
1270  dest.insert_before_swap(target, tmp);
1271  ++target;
1272  ++target;
1273 
1274  return target;
1275 }
1276 
1278  goto_programt &dest,
1279  goto_programt::targett target,
1280  const exprt &lhs,
1281  const exprt &rhs)
1282 {
1283  if(rhs.id()==ID_if)
1284  return value_assignments_if(dest, target, lhs, to_if_expr(rhs));
1285 
1286  PRECONDITION(lhs.type() == rhs.type());
1287 
1288  if(lhs.type().id()==ID_array)
1289  {
1290  const exprt &a_size=to_array_type(lhs.type()).size();
1291  const auto size = numeric_cast<mp_integer>(a_size);
1292  // don't do anything, if we cannot determine the size
1293  if(!size.has_value())
1294  return target;
1295  for(mp_integer i = 0; i < *size; ++i)
1296  target=value_assignments(dest, target,
1297  index_exprt(lhs, from_integer(i, a_size.type())),
1298  index_exprt(rhs, from_integer(i, a_size.type())));
1299  }
1300  else if(lhs.type().id() == ID_pointer)
1301  return value_assignments(
1302  dest, target, dereference_exprt{lhs}, dereference_exprt{rhs});
1303  else if(lhs.type()==string_struct)
1304  return value_assignments_string_struct(dest, target, lhs, rhs);
1305  else if(lhs.type().id()==ID_struct || lhs.type().id()==ID_union)
1306  {
1307  const struct_union_typet &struct_union_type=
1308  to_struct_union_type(lhs.type());
1309 
1310  for(const auto &comp : struct_union_type.components())
1311  {
1312  INVARIANT(
1313  !comp.get_name().empty(), "struct/union components must have a name");
1314 
1315  target=value_assignments(dest, target,
1316  member_exprt(lhs, comp.get_name(), comp.type()),
1317  member_exprt(rhs, comp.get_name(), comp.type()));
1318  }
1319  }
1320 
1321  return target;
1322 }
1323 
1325  goto_programt &dest,
1326  goto_programt::targett target,
1327  const exprt &lhs, const if_exprt &rhs)
1328 {
1329  goto_programt tmp;
1330 
1331  goto_programt::targett goto_else =
1333  boolean_negate(rhs.cond()), target->source_location()));
1335  true_exprt(), target->source_location()));
1336  goto_programt::targett else_target =
1337  tmp.add(goto_programt::make_skip(target->source_location()));
1338  goto_programt::targett out_target =
1339  tmp.add(goto_programt::make_skip(target->source_location()));
1340 
1341  goto_else->complete_goto(else_target);
1342  goto_out->complete_goto(out_target);
1343 
1344  value_assignments(tmp, goto_out, lhs, rhs.true_case());
1345  value_assignments(tmp, else_target, lhs, rhs.false_case());
1346 
1347  goto_programt::targett last=target;
1348  ++last;
1349  dest.insert_before_swap(target, tmp);
1350  --last;
1351 
1352  return last;
1353 }
1354 
1356  goto_programt &dest,
1357  goto_programt::targett target,
1358  const exprt &lhs, const exprt &rhs)
1359 {
1360  // copy all the values
1361  goto_programt tmp;
1362 
1364  code_assignt{
1365  member(lhs, whatt::IS_ZERO),
1366  member(rhs, whatt::IS_ZERO),
1367  target->source_location()},
1368  target->source_location()));
1369 
1371  code_assignt{
1372  member(lhs, whatt::LENGTH),
1373  member(rhs, whatt::LENGTH),
1374  target->source_location()},
1375  target->source_location()));
1376 
1378  code_assignt{
1379  member(lhs, whatt::SIZE),
1380  member(rhs, whatt::SIZE),
1381  target->source_location()},
1382  target->source_location()));
1383 
1384  goto_programt::targett last=target;
1385  ++last;
1386  dest.insert_before_swap(target, tmp);
1387  --last;
1388 
1389  return last;
1390 }
1391 
1393 {
1394  if(a.is_nil())
1395  return a;
1396 
1399  "either the expression is not a string or it is not a pointer to one");
1400 
1401  exprt struct_op=
1402  a.type().id()==ID_pointer?
1404 
1405  irep_idt component_name;
1406 
1407  switch(what)
1408  {
1409  case whatt::IS_ZERO: component_name="is_zero"; break;
1410  case whatt::SIZE: component_name="size"; break;
1411  case whatt::LENGTH: component_name="length"; break;
1412  }
1413 
1414  return member_exprt(struct_op, component_name, build_type(what));
1415 }
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
const T & as_const(T &value)
Return a reference to the same object but ensures the type is const.
Definition: as_const.h:14
pointer_typet pointer_type(const typet &subtype)
Definition: c_types.cpp:235
typet c_bool_type()
Definition: c_types.cpp:100
bitvector_typet c_index_type()
Definition: c_types.cpp:16
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
Definition: c_types.h:224
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:1621
Array constructor from single element.
Definition: std_expr.h:1558
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
Internally generated symbol table entryThis is a symbol generated as part of translation to or modifi...
Definition: symbol.h:153
exprt & op0()
Definition: expr.h:133
A base class for relations, i.e., binary predicates whose two operands have the same type.
Definition: std_expr.h:762
A goto_instruction_codet representing an assignment in the program.
A goto_instruction_codet representing the declaration of a local variable.
exprt::operandst argumentst
Base type of functions.
Definition: std_types.h:583
std::vector< parametert > parameterst
Definition: std_types.h:585
const parameterst & parameters() const
Definition: std_types.h:699
Data structure for representing an arbitrary statement in a program.
Definition: std_code_base.h:29
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
bool empty() const
Definition: dstring.h:89
Base class for all expressions.
Definition: expr.h:56
source_locationt & add_source_location()
Definition: expr.h:236
const source_locationt & source_location() const
Definition: expr.h:231
bool is_zero() const
Return whether the expression is a constant representing 0.
Definition: expr.cpp:47
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
static irep_idt entry_point()
Get the identifier of the entry point to a goto model.
std::vector< irep_idt > parameter_identifierst
Definition: goto_function.h:28
symbol_tablet symbol_table
Symbol table.
Definition: goto_model.h:31
goto_functionst goto_functions
GOTO functions.
Definition: goto_model.h:34
This class represents an instruction in the GOTO intermediate representation.
Definition: goto_program.h:181
A generic container class for the GOTO intermediate representation of one function.
Definition: goto_program.h:73
instructionst instructions
The list of instructions in the goto program.
Definition: goto_program.h:622
void clear()
Clear the goto program.
Definition: goto_program.h:820
void insert_before_swap(targett target)
Insertion that preserves jumps to "target".
Definition: goto_program.h:643
instructionst::iterator targett
Definition: goto_program.h:614
void destructive_append(goto_programt &p)
Appends the given program p to *this. p is destroyed.
Definition: goto_program.h:722
static instructiont make_assignment(const code_assignt &_code, const source_locationt &l=source_locationt::nil())
Create an assignment instruction.
static instructiont make_skip(const source_locationt &l=source_locationt::nil())
Definition: goto_program.h:891
void swap(goto_programt &program)
Swap the goto program.
Definition: goto_program.h:814
targett add(instructiont &&instruction)
Adds a given instruction at the end.
Definition: goto_program.h:739
static instructiont make_decl(const symbol_exprt &symbol, const source_locationt &l=source_locationt::nil())
Definition: goto_program.h:964
static instructiont make_incomplete_goto(const exprt &_cond, const source_locationt &l=source_locationt::nil())
The trinary if-then-else operator.
Definition: std_expr.h:2375
exprt & true_case()
Definition: std_expr.h:2402
exprt & false_case()
Definition: std_expr.h:2412
exprt & cond()
Definition: std_expr.h:2392
Array index operator.
Definition: std_expr.h:1470
exprt & array()
Definition: std_expr.h:1500
exprt & index()
Definition: std_expr.h:1510
const irept & find(const irep_idt &name) const
Definition: irep.cpp:93
bool is_not_nil() const
Definition: irep.h:372
const irep_idt & id() const
Definition: irep.h:388
void make_nil()
Definition: irep.h:446
void swap(irept &irep)
Definition: irep.h:434
bool is_nil() const
Definition: irep.h:368
Extract member of struct or union.
Definition: std_expr.h:2849
const exprt & struct_op() const
Definition: std_expr.h:2887
irep_idt get_component_name() const
Definition: std_expr.h:2871
Class that provides messages with a built-in verbosity 'level'.
Definition: message.h:154
static eomt eom
Definition: message.h:289
Binary minus.
Definition: std_expr.h:1061
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
Definition: namespace.cpp:63
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Definition: namespace.cpp:148
The NIL expression.
Definition: std_expr.h:3086
The plus expression Associativity is not specified.
Definition: std_expr.h:1002
const typet & base_type() const
The type of the data what we point to.
Definition: pointer_expr.h:35
A side_effect_exprt that returns a non-deterministically chosen value.
Definition: std_code.h:1520
Replace all uses of char * by a struct that carries that string, and also the underlying allocation a...
goto_programt::targett abstract(goto_programt &dest, goto_programt::targett it)
goto_programt::targett value_assignments_if(goto_programt &dest, goto_programt::targett target, const exprt &lhs, const if_exprt &rhs)
goto_programt::targett value_assignments_string_struct(goto_programt &dest, goto_programt::targett target, const exprt &lhs, const exprt &rhs)
void declare_define_locals(goto_programt &dest)
goto_modelt & goto_model
exprt make_val_or_dummy_rec(goto_programt &dest, goto_programt::targett ref_instr, const symbolt &symbol, const typet &source_type)
bool build_symbol_constant(const mp_integer &zero_length, const mp_integer &buf_size, exprt &dest)
goto_programt::targett abstract_assign(goto_programt &dest, goto_programt::targett it)
static typet build_type(whatt what)
goto_programt::targett abstract_pointer_assign(goto_programt &dest, goto_programt::targett it)
bool build_if(const if_exprt &o_if, exprt &dest, bool write)
const typet & build_abstraction_type_rec(const typet &type, const abstraction_types_mapt &known)
void replace_string_macros(exprt &expr, bool lhs, const source_locationt &)
exprt build_unknown(whatt what, bool write)
string_abstractiont(goto_modelt &goto_model, message_handlert &_message_handler)
Apply string abstraction to goto_model.
void build_new_symbol(const symbolt &symbol, const irep_idt &identifier, const typet &type)
bool is_ptr_string_struct(const typet &type) const
message_handlert & message_handler
::std::map< typet, typet > abstraction_types_mapt
goto_programt initialization
goto_programt::targett value_assignments(goto_programt &dest, goto_programt::targett it, const exprt &lhs, const exprt &rhs)
symbol_exprt add_dummy_symbol_and_value(goto_programt &dest, goto_programt::targett ref_instr, const symbolt &symbol, const irep_idt &component_name, const typet &type, const typet &source_type)
bool build_wrap(const exprt &object, exprt &dest, bool write)
goto_programt::targett abstract_char_assign(goto_programt &dest, goto_programt::targett it)
bool build_array(const array_exprt &object, exprt &dest, bool write)
bool build_symbol(const symbol_exprt &sym, exprt &dest)
void move_lhs_arithmetic(exprt &lhs, exprt &rhs)
abstraction_types_mapt abstraction_types_map
goto_programt::targett char_assign(goto_programt &dest, goto_programt::targett target, const exprt &new_lhs, const exprt &lhs, const exprt &rhs)
code_typet::parametert add_parameter(const symbolt &fct_symbol, const typet &type, const irep_idt &identifier)
bool build_pointer(const exprt &object, exprt &dest, bool write)
void abstract_function_call(goto_programt::targett it)
exprt member(const exprt &a, whatt what)
static bool has_string_macros(const exprt &expr)
exprt build(const exprt &pointer, whatt what, bool write, const source_locationt &)
void make_decl_and_def(goto_programt &dest, goto_programt::targett ref_instr, const irep_idt &identifier, const irep_idt &source_sym)
void add_str_parameters(symbolt &fct_symbol, goto_functiont::parameter_identifierst &parameter_identifiers)
bool is_char_type(const typet &type) const
const typet & build_abstraction_type(const typet &type)
Struct constructor from list of elements.
Definition: std_expr.h:1877
A struct tag type, i.e., struct_typet with an identifier.
Definition: std_types.h:493
Structure type, corresponds to C style structs.
Definition: std_types.h:231
Base type for structs and unions.
Definition: std_types.h:62
const componentst & components() const
Definition: std_types.h:147
std::vector< componentt > componentst
Definition: std_types.h:140
Expression to hold a symbol (variable)
Definition: std_expr.h:131
const irep_idt & get_identifier() const
Definition: std_expr.h:160
std::vector< irep_idt > sorted_symbol_names() const
Build and return a lexicographically sorted vector of symbol names from all symbols stored in this sy...
symbolt & get_writeable_ref(const irep_idt &name)
Find a symbol in the symbol table for read-write access.
bool has_symbol(const irep_idt &name) const
Check whether a symbol exists in the symbol table.
The symbol table.
Definition: symbol_table.h:14
virtual std::pair< symbolt &, bool > insert(symbolt symbol) override
Author: Diffblue Ltd.
Symbol table entry.
Definition: symbol.h:28
irep_idt base_name
Base (non-scoped) name.
Definition: symbol.h:46
bool is_auxiliary
Definition: symbol.h:77
bool is_macro
Definition: symbol.h:62
bool is_file_local
Definition: symbol.h:73
irep_idt module
Name of module the symbol belongs to.
Definition: symbol.h:43
bool is_static_lifetime
Definition: symbol.h:70
bool is_parameter
Definition: symbol.h:76
bool is_thread_local
Definition: symbol.h:71
bool is_type
Definition: symbol.h:61
source_locationt location
Source code location of definition of symbol.
Definition: symbol.h:37
bool is_state_var
Definition: symbol.h:66
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
Definition: symbol.cpp:121
typet type
Type of symbol.
Definition: symbol.h:31
irep_idt name
The unique identifier.
Definition: symbol.h:40
irep_idt pretty_name
Language-specific display name.
Definition: symbol.h:52
bool is_lvalue
Definition: symbol.h:72
exprt value
Initial value of symbol.
Definition: symbol.h:34
irep_idt mode
Language mode.
Definition: symbol.h:49
The Boolean constant true.
Definition: std_expr.h:3068
const typet & subtype() const
Definition: type.h:187
Semantic type conversion.
Definition: std_expr.h:2073
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition: std_expr.h:2081
The type of an expression, extends irept.
Definition: type.h:29
source_locationt & add_source_location()
Definition: type.h:77
const exprt & op() const
Definition: std_expr.h:391
A union tag type, i.e., union_typet with an identifier.
Definition: c_types.h:199
#define Forall_operands(it, expr)
Definition: expr.h:27
exprt boolean_negate(const exprt &src)
negate a Boolean expression, possibly removing a not_exprt, and swapping false and true
Definition: expr_util.cpp:103
Deprecated expression utility functions.
int main(int argc, char *argv[])
symbolt & get_fresh_aux_symbol(const typet &type, const std::string &name_prefix, const std::string &basename_prefix, const source_locationt &source_location, const irep_idt &symbol_mode, const namespacet &ns, symbol_table_baset &symbol_table)
Installs a fresh-named symbol with respect to the given namespace ns with the requested name pattern ...
Fresh auxiliary symbol creation.
Symbol Table + CFG.
#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
@ 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
const std::string & id2string(const irep_idt &d)
Definition: irep.h:44
double log(double x)
Definition: math.c:2776
const std::string integer2string(const mp_integer &n, unsigned base)
Definition: mp_arith.cpp:103
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 pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
Definition: pointer_expr.h:93
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
Definition: pointer_expr.h:577
exprt pointer_offset(const exprt &pointer)
Various predicates over pointers in programs.
BigInt mp_integer
Definition: smt_terms.h:17
#define PRECONDITION_WITH_DIAGNOSTICS(CONDITION,...)
Definition: invariant.h:464
#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:2455
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:1665
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition: std_expr.h:2107
const minus_exprt & to_minus_expr(const exprt &expr)
Cast an exprt to a minus_exprt.
Definition: std_expr.h:1086
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition: std_expr.h:2941
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition: std_expr.h:426
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition: std_expr.h:1538
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition: std_types.h:788
bool is_constant(const typet &type)
This method tests, if the given typet is a constant.
Definition: std_types.h:29
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition: std_types.h:888
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
Definition: std_types.h:214
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
Definition: std_types.h:518
const struct_or_union_tag_typet & to_struct_or_union_tag_type(const typet &type)
Cast a typet to a struct_or_union_tag_typet.
Definition: std_types.h:478
const tag_typet & to_tag_type(const typet &type)
Cast a typet to a tag_typet.
Definition: std_types.h:434
void string_abstraction(goto_modelt &goto_model, message_handlert &message_handler)
static bool is_ptr_argument(const typet &type)
String Abstraction.
const string_constantt & to_string_constant(const exprt &expr)
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition: type.h:208
ssize_t write(int fildes, const void *buf, size_t nbyte)
Definition: unistd.c:195
#define size_type
Definition: unistd.c:347
dstringt irep_idt