CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
string_abstraction.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: String Abstraction
4
5Author: 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>
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 &&
64 to_pointer_type(type).base_type() == string_struct;
65}
66
67static 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,
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
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
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
194 goto_functiont::parameter_identifierst &parameter_identifiers)
195{
197 PRECONDITION(fct_type.parameters().size() == parameter_identifiers.size());
198
200
201 goto_functiont::parameter_identifierst::const_iterator param_id_it =
202 parameter_identifiers.begin();
203 for(const auto &parameter : fct_type.parameters())
204 {
206 if(abstract_type.is_nil())
207 continue;
208
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
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
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
263 locals.clear();
264}
265
267{
268 typedef std::unordered_map<irep_idt, goto_programt::targett> available_declst;
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 {
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
293 make_decl_and_def(tmp, ref_instr, l.second, l.first);
294
295 if(has_decl)
296 ++ref_instr;
298 }
299}
300
303 const irep_idt &identifier,
304 const irep_idt &source_sym)
305{
306 const symbolt &symbol=ns.lookup(identifier);
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 {
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
332 const symbolt &symbol, const typet &source_type)
333{
334 if(symbol.type.id() == ID_array || symbol.type.id() == ID_pointer)
335 {
340 dest,
341 ref_instr,
342 symbol,
343 irep_idt(),
344 to_type_with_subtype(symbol.type).subtype(),
346
347 if(symbol.type.id() == ID_array)
348 return array_of_exprt(sym_expr, to_array_type(symbol.type));
349 else
351 }
352 else if(
353 symbol.type.id() == ID_union_tag ||
354 (symbol.type.id() == ID_struct_tag && symbol.type != string_struct))
355 {
358 const struct_union_typet::componentst &components =
359 ns.follow_tag(to_struct_or_union_tag_type(symbol.type)).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,
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
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(
440 ? build_unknown(whatt::SIZE, false)
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
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:
506 break;
507 }
508
509 return it;
510}
511
513 goto_programt &dest,
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
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 &&
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
567 str_args.back()=address_of_exprt(idx);
568 }
569
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 ||
648 !is_char_type(to_pointer_type(op.type()).base_type()))
649 {
650 return build_unknown(what, write);
651 }
652
653 // recursive call
654 return build(op, what, write, source_location);
655 }
656
658 if(build_wrap(pointer, str_struct, write))
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();
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);
682 return map_entry->second;
683
687
689 abstraction_types_map.insert(tmp.begin(), tmp.end());
690 map_entry = abstraction_types_map.find(type);
692 return map_entry->second;
693}
694
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 =
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 {
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;
742 if(subt.is_nil())
743 // also precludes structs with pointers to the same datatype
744 continue;
745
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 {
754 abstracted_type.components().swap(new_comp);
755
757 ns.lookup(to_tag_type(type).get_identifier());
760 "",
762 existing_tag_symbol.location,
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)
776 else
778 }
779 }
780
781 return map_entry.first->second;
782}
783
784bool 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 {
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:
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
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);
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);
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();
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 {
1069 codet{ID_nil},
1070 symbol.location,
1072 {},
1073 {}});
1074 make_decl_and_def(initialization, dummy_loc, identifier, symbol.name);
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)
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(
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 {
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 {
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
1159 if(abstract_type.is_nil())
1160 return target;
1161
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)
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,
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 {
1209 INVARIANT(
1210 i2.is_not_nil(),
1211 "failed to create length-component for the left-hand-side");
1212
1214 typecast_exprt::conditional_cast(i_lhs.index(), i2.type());
1215
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 {
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,
1250 const exprt &new_lhs,
1251 const exprt &lhs,
1252 const exprt &rhs)
1253{
1255
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,
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 {
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,
1327 const exprt &lhs, const if_exprt &rhs)
1328{
1330
1333 boolean_negate(rhs.cond()), target->source_location()));
1335 true_exprt(), target->source_location()));
1337 tmp.add(goto_programt::make_skip(target->source_location()));
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
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,
1358 const exprt &lhs, const exprt &rhs)
1359{
1360 // copy all the values
1362
1365 member(lhs, whatt::IS_ZERO),
1366 member(rhs, whatt::IS_ZERO),
1367 target->source_location()},
1368 target->source_location()));
1369
1372 member(lhs, whatt::LENGTH),
1373 member(rhs, whatt::LENGTH),
1374 target->source_location()},
1375 target->source_location()));
1376
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
1398 a.type() == string_struct || is_ptr_string_struct(a.type()),
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.
virtual void clear()
Reset the abstract state.
Definition ai.h:265
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
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
Internally generated symbol table entryThis is a symbol generated as part of translation to or modifi...
Definition symbol.h:153
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.
Base type of functions.
Definition std_types.h:583
std::vector< parametert > parameterst
Definition std_types.h:586
Data structure for representing an arbitrary statement in a program.
Operator to dereference a pointer.
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
typet & type()
Return the type of the expression.
Definition expr.h:84
operandst & operands()
Definition expr.h:94
const source_locationt & source_location() const
Definition expr.h:231
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
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.
A generic container class for the GOTO intermediate representation of one function.
instructionst instructions
The list of instructions in the goto program.
void clear()
Clear the goto program.
void insert_before_swap(targett target)
Insertion that preserves jumps to "target".
instructionst::iterator targett
void destructive_append(goto_programt &p)
Appends the given program p to *this. p is destroyed.
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())
void swap(goto_programt &program)
Swap the goto program.
targett add(instructiont &&instruction)
Adds a given instruction at the end.
static instructiont make_decl(const symbol_exprt &symbol, const source_locationt &l=source_locationt::nil())
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:2497
exprt & cond()
Definition std_expr.h:2514
exprt & false_case()
Definition std_expr.h:2534
exprt & true_case()
Definition std_expr.h:2524
Array index operator.
Definition std_expr.h:1470
bool is_not_nil() const
Definition irep.h:372
void make_nil()
Definition irep.h:446
void swap(irept &irep)
Definition irep.h:434
const irep_idt & id() const
Definition irep.h:388
bool is_nil() const
Definition irep.h:368
Extract member of struct or union.
Definition std_expr.h:2971
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:49
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
The NIL expression.
Definition std_expr.h:3208
The plus expression Associativity is not specified.
Definition std_expr.h:1002
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)
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::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
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.
virtual std::pair< symbolt &, bool > insert(symbolt symbol) override
Author: Diffblue Ltd.
Symbol table entry.
Definition symbol.h:28
bool is_file_local
Definition symbol.h:73
bool is_static_lifetime
Definition symbol.h:70
bool is_parameter
Definition symbol.h:76
bool is_thread_local
Definition symbol.h:71
source_locationt location
Source code location of definition of symbol.
Definition symbol.h:37
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
irep_idt irep_idt base_name
Name of module the symbol belongs to.
Definition symbol.h:46
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:3190
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
A union tag type, i.e., union_typet with an identifier.
Definition c_types.h:199
int main()
Definition example.cpp:18
#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
Deprecated expression utility functions.
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
@ ATOMIC_END
@ DEAD
@ LOCATION
@ END_FUNCTION
@ ASSIGN
@ ASSERT
@ SET_RETURN_VALUE
@ ATOMIC_BEGIN
@ CATCH
@ END_THREAD
@ SKIP
@ NO_INSTRUCTION_TYPE
@ START_THREAD
@ THROW
@ DECL
@ OTHER
@ GOTO
@ INCOMPLETE_GOTO
@ ASSUME
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
double log(double x)
Definition math.c:2449
const std::string integer2string(const mp_integer &n, unsigned base)
Definition mp_arith.cpp:103
API to expression classes for Pointers.
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
const dereference_exprt & to_dereference_expr(const exprt &expr)
Cast an exprt to a dereference_exprt.
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
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition std_expr.h:1538
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 unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition std_expr.h:426
const if_exprt & to_if_expr(const exprt &expr)
Cast an exprt to an if_exprt.
Definition std_expr.h:2577
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition std_expr.h:3063
const minus_exprt & to_minus_expr(const exprt &expr)
Cast an exprt to a minus_exprt.
Definition std_expr.h:1086
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition std_expr.h:272
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 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 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 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)
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:186
dstringt irep_idt