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