CBMC
Loading...
Searching...
No Matches
expr2c.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module:
4
5Author: Daniel Kroening, [email protected]
6
7\*******************************************************************/
8
9#include "expr2c.h"
10#include "expr2c_class.h"
11
12#include <util/arith_tools.h>
13#include <util/c_types.h>
14#include <util/config.h>
15#include <util/cprover_prefix.h>
16#include <util/find_symbols.h>
17#include <util/fixedbv.h>
18#include <util/floatbv_expr.h>
19#include <util/lispexpr.h>
20#include <util/lispirep.h>
21#include <util/namespace.h>
22#include <util/pointer_expr.h>
24#include <util/prefix.h>
26#include <util/string_utils.h>
27#include <util/suffix.h>
28#include <util/symbol.h>
29
30#include "c_misc.h"
31#include "c_qualifiers.h"
32
33#include <algorithm>
34#include <map>
35#include <sstream>
36
37// clang-format off
38
40{
41 true,
42 true,
43 true,
44 "TRUE",
45 "FALSE",
46 true,
47 false,
48 false
49};
50
52{
53 false,
54 false,
55 false,
56 "1",
57 "0",
58 false,
59 true,
60 true
61};
62
63// clang-format on
64/*
65
66Precedences are as follows. Higher values mean higher precedence.
67
6816 function call ()
69 ++ -- [] . ->
70
711 comma
72
73*/
74
75irep_idt expr2ct::id_shorthand(const irep_idt &identifier) const
76{
77 const symbolt *symbol;
78
79 if(!ns.lookup(identifier, symbol) &&
80 !symbol->base_name.empty() &&
81 has_suffix(id2string(identifier), id2string(symbol->base_name)))
82 return symbol->base_name;
83
84 std::string sh=id2string(identifier);
85
86 std::string::size_type pos=sh.rfind("::");
87 if(pos!=std::string::npos)
88 sh.erase(0, pos+2);
89
90 return sh;
91}
92
93static std::string clean_identifier(const irep_idt &id)
94{
95 std::string dest=id2string(id);
96
97 std::string::size_type c_pos=dest.find("::");
98 if(c_pos!=std::string::npos &&
99 dest.rfind("::")==c_pos)
100 dest.erase(0, c_pos+2);
101 else if(c_pos!=std::string::npos)
102 {
103 for(char &ch : dest)
104 if(ch == ':')
105 ch = '$';
106 else if(ch == '-')
107 ch = '_';
108 }
109
110 // rewrite . as used in ELF section names
111 std::replace(dest.begin(), dest.end(), '.', '_');
112
113 return dest;
114}
115
117{
118 const std::unordered_set<irep_idt> symbols = find_symbol_identifiers(expr);
119
120 // avoid renaming parameters, if possible
121 for(const auto &symbol_id : symbols)
122 {
123 const symbolt *symbol;
124 bool is_param = !ns.lookup(symbol_id, symbol) && symbol->is_parameter;
125
126 if(!is_param)
127 continue;
128
130
131 std::string func = id2string(symbol_id);
132 func = func.substr(0, func.rfind("::"));
133
134 // if there is a global symbol of the same name as the shorthand (even if
135 // not present in this particular expression) then there is a collision
136 const symbolt *global_symbol;
137 if(!ns.lookup(sh, global_symbol))
138 sh = func + "$$" + id2string(sh);
139
140 ns_collision[func].insert(sh);
141
142 if(!shorthands.insert(std::make_pair(symbol_id, sh)).second)
144 }
145
146 for(const auto &symbol_id : symbols)
147 {
148 if(shorthands.find(symbol_id) != shorthands.end())
149 continue;
150
152
153 bool has_collision=
154 ns_collision[irep_idt()].find(sh)!=
155 ns_collision[irep_idt()].end();
156
157 if(!has_collision)
158 {
159 // if there is a global symbol of the same name as the shorthand (even if
160 // not present in this particular expression) then there is a collision
161 const symbolt *symbol;
162 has_collision=!ns.lookup(sh, symbol);
163 }
164
165 if(!has_collision)
166 {
168
169 const symbolt *symbol;
170 // we use the source-level function name as a means to detect collisions,
171 // which is ok, because this is about generating user-visible output
172 if(!ns.lookup(symbol_id, symbol))
173 func=symbol->location.get_function();
174
175 has_collision=!ns_collision[func].insert(sh).second;
176 }
177
178 if(!has_collision)
179 {
180 // We could also conflict with a function argument, the code below
181 // finds the function we're in, and checks we don't conflict with
182 // any argument to the function
183 const std::string symbol_str = id2string(symbol_id);
184 const std::string func = symbol_str.substr(0, symbol_str.find("::"));
185 const symbolt *func_symbol;
186 if(!ns.lookup(func, func_symbol))
187 {
189 {
190 const auto func_type =
192 const auto params = func_type.parameters();
193 for(const auto &param : params)
194 {
195 const auto param_id = param.get_identifier();
197 {
198 has_collision = true;
199 break;
200 }
201 }
202 }
203 }
204 }
205
206 if(has_collision)
208
209 shorthands.insert(std::make_pair(symbol_id, sh));
210 }
211}
212
213std::string expr2ct::convert(const typet &src)
214{
215 return convert_with_identifier(src, "");
216}
217
219 const typet &src,
221 const std::string &declarator)
222{
223 std::unique_ptr<c_qualifierst> clone = qualifiers.clone();
225 new_qualifiers.read(src);
226
227 std::string q=new_qualifiers.as_string();
228
229 std::string d = declarator.empty() ? declarator : " " + declarator;
230
231 if(!configuration.expand_typedef && src.find(ID_C_typedef).is_not_nil())
232 {
233 return q+id2string(src.get(ID_C_typedef))+d;
234 }
235
236 if(src.id()==ID_bool)
237 {
238 return q + CPROVER_PREFIX + "bool" + d;
239 }
240 else if(src.id()==ID_c_bool)
241 {
242 return q+"_Bool"+d;
243 }
244 else if(src.id()==ID_string)
245 {
246 return q + CPROVER_PREFIX + "string" + d;
247 }
248 else if(src.id()==ID_natural ||
249 src.id()==ID_integer ||
250 src.id()==ID_rational)
251 {
252 return q+src.id_string()+d;
253 }
254 else if(src.id()==ID_empty)
255 {
256 return q+"void"+d;
257 }
258 else if(src.id()==ID_complex)
259 {
260 // these take more or less arbitrary subtypes
261 return q + "_Complex " + convert(to_complex_type(src).subtype()) + d;
262 }
263 else if(src.id()==ID_floatbv)
264 {
265 std::size_t width=to_floatbv_type(src).get_width();
266
267 if(width==config.ansi_c.single_width)
268 return q+"float"+d;
269 else if(width==config.ansi_c.double_width)
270 return q+"double"+d;
271 else if(width==config.ansi_c.long_double_width)
272 return q+"long double"+d;
273 else
274 {
275 std::string swidth = std::to_string(width);
276 std::string fwidth=src.get_string(ID_f);
277 return q + CPROVER_PREFIX + "floatbv[" + swidth + "][" + fwidth + "]";
278 }
279 }
280 else if(src.id()==ID_fixedbv)
281 {
282 const std::size_t width=to_fixedbv_type(src).get_width();
283
284 const std::size_t fraction_bits=to_fixedbv_type(src).get_fraction_bits();
285 return q + CPROVER_PREFIX + "fixedbv[" + std::to_string(width) + "][" +
286 std::to_string(fraction_bits) + "]" + d;
287 }
288 else if(src.id()==ID_c_bit_field)
289 {
290 std::string width=std::to_string(to_c_bit_field_type(src).get_width());
291 return q + convert(to_c_bit_field_type(src).underlying_type()) + d + " : " +
292 width;
293 }
294 else if(src.id()==ID_signedbv ||
295 src.id()==ID_unsignedbv)
296 {
297 // annotated?
299 const std::string c_type_str=c_type_as_string(c_type);
300
301 if(c_type==ID_char &&
302 config.ansi_c.char_is_unsigned!=(src.id()==ID_unsignedbv))
303 {
304 if(src.id()==ID_signedbv)
305 return q+"signed char"+d;
306 else
307 return q+"unsigned char"+d;
308 }
309 else if(c_type!=ID_wchar_t && !c_type_str.empty())
310 return q+c_type_str+d;
311
312 // There is also wchar_t among the above, but this isn't a C type.
313
314 const std::size_t width = to_bitvector_type(src).get_width();
315
316 bool is_signed=src.id()==ID_signedbv;
317 std::string sign_str=is_signed?"signed ":"unsigned ";
318
319 if(width==config.ansi_c.int_width)
320 {
321 if(is_signed)
322 sign_str.clear();
323 return q+sign_str+"int"+d;
324 }
325 else if(width==config.ansi_c.long_int_width)
326 {
327 if(is_signed)
328 sign_str.clear();
329 return q+sign_str+"long int"+d;
330 }
331 else if(width==config.ansi_c.char_width)
332 {
333 // always include sign
334 return q+sign_str+"char"+d;
335 }
336 else if(width==config.ansi_c.short_int_width)
337 {
338 if(is_signed)
339 sign_str.clear();
340 return q+sign_str+"short int"+d;
341 }
342 else if(width==config.ansi_c.long_long_int_width)
343 {
344 if(is_signed)
345 sign_str.clear();
346 return q+sign_str+"long long int"+d;
347 }
348 else if(width==128)
349 {
350 if(is_signed)
351 sign_str.clear();
352 return q + sign_str + "__int128" + d;
353 }
354 else
355 {
356 return q + sign_str + CPROVER_PREFIX + "bitvector[" +
357 integer2string(width) + "]" + d;
358 }
359 }
360 else if(src.id()==ID_struct)
361 {
362 return convert_struct_type(src, q, d);
363 }
364 else if(src.id()==ID_union)
365 {
367
368 std::string dest=q+"union";
369
370 const irep_idt &tag=union_type.get_tag();
371 if(!tag.empty())
372 dest+=" "+id2string(tag);
373
374 if(!union_type.is_incomplete())
375 {
376 dest += " {";
377
378 for(const auto &c : union_type.components())
379 {
380 dest += ' ';
381 dest += convert_with_identifier(c.type(), id2string(c.get_name()));
382 dest += ';';
383 }
384
385 dest += " }";
386 }
387
388 dest+=d;
389
390 return dest;
391 }
392 else if(src.id()==ID_c_enum)
393 {
394 std::string result;
395 result+=q;
396 result+="enum";
397
398 // do we have a tag?
399 const irept &tag=src.find(ID_tag);
400
401 if(tag.is_nil())
402 {
403 }
404 else
405 {
406 result+=' ';
407 result+=tag.get_string(ID_C_base_name);
408 }
409
410 result+=' ';
411
412 if(!to_c_enum_type(src).is_incomplete())
413 {
415 const bool is_signed = c_enum_type.underlying_type().id() == ID_signedbv;
416 const auto width =
417 to_bitvector_type(c_enum_type.underlying_type()).get_width();
418
419 result += '{';
420
421 // add members
422 const c_enum_typet::memberst &members = c_enum_type.members();
423
424 for(c_enum_typet::memberst::const_iterator it = members.begin();
425 it != members.end();
426 it++)
427 {
428 mp_integer int_value = bvrep2integer(it->get_value(), width, is_signed);
429
430 if(it != members.begin())
431 result += ',';
432 result += ' ';
433 result += id2string(it->get_base_name());
434 result += '=';
435 result += integer2string(int_value);
436 }
437
438 result += " }";
439 }
440
441 result += d;
442 return result;
443 }
444 else if(src.id()==ID_c_enum_tag)
445 {
447 const symbolt &symbol=ns.lookup(c_enum_tag_type);
448 std::string result=q+"enum";
449 result+=" "+id2string(symbol.base_name);
450 result+=d;
451 return result;
452 }
453 else if(src.id()==ID_pointer)
454 {
456 const typet &base_type = to_pointer_type(src).base_type();
457 sub_qualifiers.read(base_type);
458
459 // The star gets attached to the declarator.
460 std::string new_declarator="*";
461
462 if(!q.empty() && (!declarator.empty() || base_type.id() == ID_pointer))
463 {
464 new_declarator+=" "+q;
465 }
466
467 new_declarator+=declarator;
468
469 // Depending on precedences, we may add parentheses.
470 if(
471 base_type.id() == ID_code ||
472 (sizeof_nesting == 0 && base_type.id() == ID_array))
473 {
475 }
476
477 return convert_rec(base_type, sub_qualifiers, new_declarator);
478 }
479 else if(src.id()==ID_array)
480 {
481 return convert_array_type(src, qualifiers, declarator);
482 }
483 else if(src.id()==ID_struct_tag)
484 {
487
488 std::string dest=q+"struct";
489 const std::string &tag=ns.follow_tag(struct_tag_type).get_string(ID_tag);
490 if(!tag.empty())
491 dest+=" "+tag;
492 dest+=d;
493
494 return dest;
495 }
496 else if(src.id()==ID_union_tag)
497 {
500
501 std::string dest=q+"union";
502 const std::string &tag=ns.follow_tag(union_tag_type).get_string(ID_tag);
503 if(!tag.empty())
504 dest+=" "+tag;
505 dest+=d;
506
507 return dest;
508 }
509 else if(src.id()==ID_code)
510 {
512
513 // C doesn't really have syntax for function types,
514 // i.e., the following won't parse without declarator
515 std::string dest=declarator+"(";
516
517 const code_typet::parameterst &parameters=code_type.parameters();
518
519 if(parameters.empty())
520 {
521 if(!code_type.has_ellipsis())
522 dest+="void"; // means 'no parameters'
523 }
524 else
525 {
526 for(code_typet::parameterst::const_iterator
527 it=parameters.begin();
528 it!=parameters.end();
529 it++)
530 {
531 if(it!=parameters.begin())
532 dest+=", ";
533
534 if(it->get_identifier().empty())
535 dest+=convert(it->type());
536 else
537 {
538 std::string arg_declarator=
539 convert(symbol_exprt(it->get_identifier(), it->type()));
540 dest += convert_with_identifier(it->type(), arg_declarator);
541 }
542 }
543
544 if(code_type.has_ellipsis())
545 dest+=", ...";
546 }
547
548 dest+=')';
549
551 ret_qualifiers.read(code_type.return_type());
552 // _Noreturn should go with the return type
553 if(new_qualifiers.is_noreturn)
554 {
555 ret_qualifiers.is_noreturn=true;
556 new_qualifiers.is_noreturn=false;
557 q=new_qualifiers.as_string();
558 }
559
560 const typet &return_type=code_type.return_type();
561
562 // return type may be a function pointer or array
563 const typet *non_ptr_type = &return_type;
564 while(non_ptr_type->id()==ID_pointer)
565 non_ptr_type = &(to_pointer_type(*non_ptr_type).base_type());
566
567 if(non_ptr_type->id()==ID_code ||
568 non_ptr_type->id()==ID_array)
569 dest=convert_rec(return_type, ret_qualifiers, dest);
570 else
571 dest=convert_rec(return_type, ret_qualifiers, "")+" "+dest;
572
573 if(!q.empty())
574 {
575 dest+=" "+q;
576 // strip trailing space off q
577 if(dest[dest.size()-1]==' ')
578 dest.resize(dest.size()-1);
579 }
580
581 return dest;
582 }
583 else if(src.id()==ID_vector)
584 {
586
588 std::string dest="__gcc_v"+integer2string(size_int);
589
590 std::string tmp = convert(vector_type.element_type());
591
592 if(tmp=="signed char" || tmp=="char")
593 dest+="qi";
594 else if(tmp=="signed short int")
595 dest+="hi";
596 else if(tmp=="signed int")
597 dest+="si";
598 else if(tmp=="signed long long int")
599 dest+="di";
600 else if(tmp=="float")
601 dest+="sf";
602 else if(tmp=="double")
603 dest+="df";
604 else
605 {
606 const std::string subtype = convert(vector_type.element_type());
607 dest=subtype;
608 dest+=" __attribute__((vector_size (";
609 dest+=convert(vector_type.size());
610 dest+="*sizeof("+subtype+"))))";
611 }
612
613 return q+dest+d;
614 }
615 else if(src.id()==ID_constructor ||
616 src.id()==ID_destructor)
617 {
618 return q+"__attribute__(("+id2string(src.id())+")) void"+d;
619 }
620 else if(src.id() == ID_bv)
621 {
622 // annotated?
625 {
626 return "_BitInt(" + src.get_string(ID_C_c_bitint_width) + ")";
627 }
628 else if(c_type == ID_c_unsigned_bitint)
629 {
630 return "unsigned _BitInt(" + src.get_string(ID_C_c_bitint_width) + ")";
631 }
632 }
633
634 {
636 irep2lisp(src, lisp);
637 std::string dest="irep(\""+MetaString(lisp.expr2string())+"\")";
638 dest+=d;
639
640 return dest;
641 }
642}
643
651 const typet &src,
652 const std::string &qualifiers_str,
653 const std::string &declarator_str)
654{
655 return convert_struct_type(
656 src,
659 configuration.print_struct_body_in_type,
660 configuration.include_struct_padding_components);
661}
662
674 const typet &src,
675 const std::string &qualifiers,
676 const std::string &declarator,
677 bool inc_struct_body,
679{
680 // Either we are including the body (in which case it makes sense to include
681 // or exclude the parameters) or there is no body so therefore we definitely
682 // shouldn't be including the parameters
683 INVARIANT(
684 inc_struct_body || !inc_padding_components, "inconsistent configuration");
685
687
688 std::string dest=qualifiers+"struct";
689
690 const irep_idt &tag=struct_type.get_tag();
691 if(!tag.empty())
692 dest+=" "+id2string(tag);
693
694 if(inc_struct_body && !struct_type.is_incomplete())
695 {
696 dest+=" {";
697
698 for(const auto &component : struct_type.components())
699 {
700 // Skip padding parameters unless we including them
701 if(component.get_is_padding() && !inc_padding_components)
702 {
703 continue;
704 }
705
706 dest+=' ';
708 component.type(), id2string(component.get_name()));
709 dest+=';';
710 }
711
712 dest+=" }";
713 }
714
715 dest+=declarator;
716
717 return dest;
718}
719
727 const typet &src,
729 const std::string &declarator_str)
730{
731 return convert_array_type(
732 src, qualifiers, declarator_str, configuration.include_array_size);
733}
734
744 const typet &src,
746 const std::string &declarator_str,
748{
749 // The [...] gets attached to the declarator.
750 std::string array_suffix;
751
752 if(to_array_type(src).size().is_nil() || !inc_size_if_possible)
753 array_suffix="[]";
754 else
755 array_suffix="["+convert(to_array_type(src).size())+"]";
756
757 // This won't really parse without declarator.
758 // Note that qualifiers are passed down.
759 return convert_rec(
760 to_array_type(src).element_type(),
763}
764
766 const typecast_exprt &src,
767 unsigned &precedence)
768{
769 if(src.operands().size()!=1)
770 return convert_norep(src, precedence);
771
772 // some special cases
773
774 const typet &to_type = src.type();
775 const typet &from_type = src.op().type();
776
777 if(to_type.id()==ID_c_bool &&
778 from_type.id()==ID_bool)
780
781 if(to_type.id()==ID_bool &&
782 from_type.id()==ID_c_bool)
784
785 std::string dest = "(" + convert(to_type) + ")";
786
787 unsigned p;
788 std::string tmp=convert_with_precedence(src.op(), p);
789
790 if(precedence>p)
791 dest+='(';
792 dest+=tmp;
793 if(precedence>p)
794 dest+=')';
795
796 return dest;
797}
798
800 const ternary_exprt &src,
801 const std::string &symbol1,
802 const std::string &symbol2,
803 unsigned precedence)
804{
805 const exprt &op0=src.op0();
806 const exprt &op1=src.op1();
807 const exprt &op2=src.op2();
808
809 unsigned p0, p1, p2;
810
811 std::string s_op0=convert_with_precedence(op0, p0);
812 std::string s_op1=convert_with_precedence(op1, p1);
813 std::string s_op2=convert_with_precedence(op2, p2);
814
815 std::string dest;
816
817 if(precedence>=p0)
818 dest+='(';
819 dest+=s_op0;
820 if(precedence>=p0)
821 dest+=')';
822
823 dest+=' ';
824 dest+=symbol1;
825 dest+=' ';
826
827 if(precedence>=p1)
828 dest+='(';
829 dest+=s_op1;
830 if(precedence>=p1)
831 dest+=')';
832
833 dest+=' ';
834 dest+=symbol2;
835 dest+=' ';
836
837 if(precedence>=p2)
838 dest+='(';
839 dest+=s_op2;
840 if(precedence>=p2)
841 dest+=')';
842
843 return dest;
844}
845
847 const binding_exprt &src,
848 const std::string &symbol,
849 unsigned precedence)
850{
851 // our made-up syntax can only do one symbol
852 if(src.variables().size() != 1)
853 return convert_norep(src, precedence);
854
855 unsigned p0, p1;
856
857 std::string op0 = convert_with_precedence(src.variables().front(), p0);
858 std::string op1 = convert_with_precedence(src.where(), p1);
859
860 std::string dest=symbol+" { ";
861 dest += convert(src.variables().front().type());
862 dest+=" "+op0+"; ";
863 dest+=op1;
864 dest+=" }";
865
866 return dest;
867}
868
870 const exprt &src,
871 unsigned precedence)
872{
873 if(src.operands().size()<3)
874 return convert_norep(src, precedence);
875
876 unsigned p0;
877 const auto &old = to_with_expr(src).old();
878 std::string op0 = convert_with_precedence(old, p0);
879
880 std::string dest;
881
882 if(precedence>p0)
883 dest+='(';
884 dest+=op0;
885 if(precedence>p0)
886 dest+=')';
887
888 dest+=" WITH [";
889
890 for(size_t i=1; i<src.operands().size(); i+=2)
891 {
892 std::string op1, op2;
893 unsigned p1, p2;
894
895 if(i!=1)
896 dest+=", ";
897
898 if(src.operands()[i].id()==ID_member_name)
899 {
900 const irep_idt &component_name=
901 src.operands()[i].get(ID_component_name);
902
904 (old.type().id() == ID_struct_tag || old.type().id() == ID_union_tag)
905 ? ns.follow_tag(to_struct_or_union_tag_type(old.type()))
906 .get_component(component_name)
907 : to_struct_union_type(old.type()).get_component(component_name);
908 CHECK_RETURN(comp_expr.is_not_nil());
909
911
912 if(comp_expr.get_pretty_name().empty())
913 display_component_name=component_name;
914 else
915 display_component_name=comp_expr.get_pretty_name();
916
918 p1=10;
919 }
920 else
921 op1=convert_with_precedence(src.operands()[i], p1);
922
923 op2=convert_with_precedence(src.operands()[i+1], p2);
924
925 dest+=op1;
926 dest+=":=";
927 dest+=op2;
928 }
929
930 dest+=']';
931
932 return dest;
933}
934
936 const let_exprt &src,
937 unsigned precedence)
938{
939 std::string dest = "LET ";
940
941 bool first = true;
942
943 const auto &values = src.values();
944 auto values_it = values.begin();
945 for(auto &v : src.variables())
946 {
947 if(first)
948 first = false;
949 else
950 dest += ", ";
951
952 dest += convert(v) + "=" + convert(*values_it);
953 ++values_it;
954 }
955
956 dest += " IN " + convert(src.where());
957
958 return dest;
959}
960
961std::string
963{
964 std::string dest;
965
966 dest+="UPDATE(";
967
968 std::string op0, op1, op2;
969 unsigned p0, p2;
970
971 op0 = convert_with_precedence(src.op0(), p0);
972 op2 = convert_with_precedence(src.op2(), p2);
973
974 if(precedence>p0)
975 dest+='(';
976 dest+=op0;
977 if(precedence>p0)
978 dest+=')';
979
980 dest+=", ";
981
982 const exprt &designator = src.op1();
983
984 for(const auto &op : designator.operands())
985 dest += convert(op);
986
987 dest+=", ";
988
989 if(precedence>p2)
990 dest+='(';
991 dest+=op2;
992 if(precedence>p2)
993 dest+=')';
994
995 dest+=')';
996
997 return dest;
998}
999
1001 const exprt &src,
1002 unsigned precedence)
1003{
1004 if(src.operands().size()<2)
1005 return convert_norep(src, precedence);
1006
1007 bool condition=true;
1008
1009 std::string dest="cond {\n";
1010
1011 for(const auto &operand : src.operands())
1012 {
1013 unsigned p;
1014 std::string op = convert_with_precedence(operand, p);
1015
1016 if(condition)
1017 dest+=" ";
1018
1019 dest+=op;
1020
1021 if(condition)
1022 dest+=": ";
1023 else
1024 dest+=";\n";
1025
1026 condition=!condition;
1027 }
1028
1029 dest+="} ";
1030
1031 return dest;
1032}
1033
1035 const binary_exprt &src,
1036 const std::string &symbol,
1037 unsigned precedence,
1038 bool full_parentheses)
1039{
1040 const exprt &op0 = src.op0();
1041 const exprt &op1 = src.op1();
1042
1043 unsigned p0, p1;
1044
1045 std::string s_op0=convert_with_precedence(op0, p0);
1046 std::string s_op1=convert_with_precedence(op1, p1);
1047
1048 std::string dest;
1049
1050 // In pointer arithmetic, x+(y-z) is unfortunately
1051 // not the same as (x+y)-z, even though + and -
1052 // have the same precedence. We thus add parentheses
1053 // for the case x+(y-z). Similarly, (x*y)/z is not
1054 // the same as x*(y/z), but * and / have the same
1055 // precedence.
1056
1057 bool use_parentheses0=
1058 precedence>p0 ||
1060 (precedence==p0 && src.id()!=op0.id());
1061
1063 dest+='(';
1064 dest+=s_op0;
1066 dest+=')';
1067
1068 dest+=' ';
1069 dest+=symbol;
1070 dest+=' ';
1071
1072 bool use_parentheses1=
1073 precedence>p1 ||
1075 (precedence==p1 && src.id()!=op1.id());
1076
1078 dest+='(';
1079 dest+=s_op1;
1081 dest+=')';
1082
1083 return dest;
1084}
1085
1087 const exprt &src,
1088 const std::string &symbol,
1089 unsigned precedence,
1090 bool full_parentheses)
1091{
1092 if(src.operands().size()<2)
1093 return convert_norep(src, precedence);
1094
1095 std::string dest;
1096 bool first=true;
1097
1098 for(const auto &operand : src.operands())
1099 {
1100 if(first)
1101 first=false;
1102 else
1103 {
1104 if(symbol!=", ")
1105 dest+=' ';
1106 dest+=symbol;
1107 dest+=' ';
1108 }
1109
1110 unsigned p;
1111 std::string op = convert_with_precedence(operand, p);
1112
1113 // In pointer arithmetic, x+(y-z) is unfortunately
1114 // not the same as (x+y)-z, even though + and -
1115 // have the same precedence. We thus add parentheses
1116 // for the case x+(y-z). Similarly, (x*y)/z is not
1117 // the same as x*(y/z), but * and / have the same
1118 // precedence.
1119
1120 bool use_parentheses = precedence > p ||
1121 (precedence == p && full_parentheses) ||
1122 (precedence == p && src.id() != operand.id());
1123
1124 if(use_parentheses)
1125 dest+='(';
1126 dest+=op;
1127 if(use_parentheses)
1128 dest+=')';
1129 }
1130
1131 return dest;
1132}
1133
1135 const unary_exprt &src,
1136 const std::string &symbol,
1137 unsigned precedence)
1138{
1139 unsigned p;
1140 std::string op = convert_with_precedence(src.op(), p);
1141
1142 std::string dest=symbol;
1143 if(precedence>=p ||
1144 (!symbol.empty() && has_prefix(op, symbol)))
1145 dest+='(';
1146 dest+=op;
1147 if(precedence>=p ||
1148 (!symbol.empty() && has_prefix(op, symbol)))
1149 dest+=')';
1150
1151 return dest;
1152}
1153
1154std::string expr2ct::convert_allocate(const exprt &src, unsigned &precedence)
1155{
1156 if(src.operands().size() != 2)
1157 return convert_norep(src, precedence);
1158
1159 unsigned p0;
1160 std::string op0 = convert_with_precedence(to_binary_expr(src).op0(), p0);
1161
1162 unsigned p1;
1163 std::string op1 = convert_with_precedence(to_binary_expr(src).op1(), p1);
1164
1165 std::string dest = "ALLOCATE";
1166 dest += '(';
1167
1168 if(
1169 src.type().id() == ID_pointer &&
1170 to_pointer_type(src.type()).base_type().id() != ID_empty)
1171 {
1172 dest += convert(to_pointer_type(src.type()).base_type());
1173 dest+=", ";
1174 }
1175
1176 dest += op0 + ", " + op1;
1177 dest += ')';
1178
1179 return dest;
1180}
1181
1183 const exprt &src,
1184 unsigned &precedence)
1185{
1186 if(!src.operands().empty())
1187 return convert_norep(src, precedence);
1188
1189 return "NONDET("+convert(src.type())+")";
1190}
1191
1193 const exprt &src,
1194 unsigned &precedence)
1195{
1196 if(
1197 src.operands().size() != 1 ||
1198 to_code(to_unary_expr(src).op()).get_statement() != ID_block)
1199 {
1200 return convert_norep(src, precedence);
1201 }
1202
1203 return "(" +
1204 convert_code(to_code_block(to_code(to_unary_expr(src).op())), 0) + ")";
1205}
1206
1208 const exprt &src,
1209 unsigned &precedence)
1210{
1211 if(src.operands().size()==1)
1212 return "COIN(" + convert(to_unary_expr(src).op()) + ")";
1213 else
1214 return convert_norep(src, precedence);
1215}
1216
1217std::string expr2ct::convert_literal(const exprt &src)
1218{
1219 return "L("+src.get_string(ID_literal)+")";
1220}
1221
1223 const exprt &src,
1224 unsigned &precedence)
1225{
1226 if(src.operands().size()==1)
1227 return "PROB_UNIFORM(" + convert(src.type()) + "," +
1228 convert(to_unary_expr(src).op()) + ")";
1229 else
1230 return convert_norep(src, precedence);
1231}
1232
1233std::string expr2ct::convert_function(const exprt &src, const std::string &name)
1234{
1235 std::string dest=name;
1236 dest+='(';
1237
1238 forall_operands(it, src)
1239 {
1240 unsigned p;
1241 std::string op=convert_with_precedence(*it, p);
1242
1243 if(it!=src.operands().begin())
1244 dest+=", ";
1245
1246 dest+=op;
1247 }
1248
1249 dest+=')';
1250
1251 return dest;
1252}
1253
1255 const exprt &src,
1256 unsigned precedence)
1257{
1258 if(src.operands().size()!=2)
1259 return convert_norep(src, precedence);
1260
1261 unsigned p0;
1262 std::string op0 = convert_with_precedence(to_binary_expr(src).op0(), p0);
1263 if(*op0.rbegin()==';')
1264 op0.resize(op0.size()-1);
1265
1266 unsigned p1;
1267 std::string op1 = convert_with_precedence(to_binary_expr(src).op1(), p1);
1268 if(*op1.rbegin()==';')
1269 op1.resize(op1.size()-1);
1270
1271 std::string dest=op0;
1272 dest+=", ";
1273 dest+=op1;
1274
1275 return dest;
1276}
1277
1279 const exprt &src,
1280 unsigned precedence)
1281{
1282 if(
1283 src.operands().size() == 2 && to_binary_expr(src).op0().is_zero() &&
1284 to_binary_expr(src).op1().is_constant())
1285 {
1286 // This is believed to be gcc only; check if this is sensible
1287 // in MSC mode.
1288 return convert_with_precedence(to_binary_expr(src).op1(), precedence) + "i";
1289 }
1290
1291 // ISO C11 offers:
1292 // double complex CMPLX(double x, double y);
1293 // float complex CMPLXF(float x, float y);
1294 // long double complex CMPLXL(long double x, long double y);
1295
1296 const typet &subtype = to_complex_type(src.type()).subtype();
1297
1298 std::string name;
1299
1300 if(subtype==double_type())
1301 name="CMPLX";
1302 else if(subtype==float_type())
1303 name="CMPLXF";
1304 else if(subtype==long_double_type())
1305 name="CMPLXL";
1306 else
1307 name="CMPLX"; // default, possibly wrong
1308
1309 std::string dest=name;
1310 dest+='(';
1311
1312 forall_operands(it, src)
1313 {
1314 unsigned p;
1315 std::string op=convert_with_precedence(*it, p);
1316
1317 if(it!=src.operands().begin())
1318 dest+=", ";
1319
1320 dest+=op;
1321 }
1322
1323 dest+=')';
1324
1325 return dest;
1326}
1327
1329 const exprt &src,
1330 unsigned precedence)
1331{
1332 if(src.operands().size()!=1)
1333 return convert_norep(src, precedence);
1334
1335 return "ARRAY_OF(" + convert(to_unary_expr(src).op()) + ')';
1336}
1337
1339 const byte_extract_exprt &src,
1340 unsigned precedence)
1341{
1342 if(src.operands().size()!=2)
1343 return convert_norep(src, precedence);
1344
1345 unsigned p0;
1346 std::string op0 = convert_with_precedence(src.op0(), p0);
1347
1348 unsigned p1;
1349 std::string op1 = convert_with_precedence(src.op1(), p1);
1350
1351 std::string dest=src.id_string();
1352 dest+='(';
1353 dest+=op0;
1354 dest+=", ";
1355 dest+=op1;
1356 dest+=", ";
1357 dest+=convert(src.type());
1358 dest+=')';
1359
1360 return dest;
1361}
1362
1363std::string
1365{
1366 unsigned p0;
1367 std::string op0 = convert_with_precedence(src.op0(), p0);
1368
1369 unsigned p1;
1370 std::string op1 = convert_with_precedence(src.op1(), p1);
1371
1372 unsigned p2;
1373 std::string op2 = convert_with_precedence(src.op2(), p2);
1374
1375 std::string dest=src.id_string();
1376 dest+='(';
1377 dest+=op0;
1378 dest+=", ";
1379 dest+=op1;
1380 dest+=", ";
1381 dest+=op2;
1382 dest+=", ";
1383 dest += convert(src.op2().type());
1384 dest+=')';
1385
1386 return dest;
1387}
1388
1390 const exprt &src,
1391 const std::string &symbol,
1392 unsigned precedence)
1393{
1394 if(src.operands().size()!=1)
1395 return convert_norep(src, precedence);
1396
1397 unsigned p;
1398 std::string op = convert_with_precedence(to_unary_expr(src).op(), p);
1399
1400 std::string dest;
1401 if(precedence>p)
1402 dest+='(';
1403 dest+=op;
1404 if(precedence>p)
1405 dest+=')';
1406 dest+=symbol;
1407
1408 return dest;
1409}
1410
1411std::string expr2ct::convert_index(const binary_exprt &src, unsigned precedence)
1412{
1413 unsigned p;
1414 std::string op = convert_with_precedence(src.op0(), p);
1415
1416 std::string dest;
1417 if(precedence>p)
1418 dest+='(';
1419 dest+=op;
1420 if(precedence>p)
1421 dest+=')';
1422
1423 dest+='[';
1424 dest += convert(src.op1());
1425 dest+=']';
1426
1427 return dest;
1428}
1429
1431 const exprt &src, unsigned &precedence)
1432{
1433 if(src.operands().size()!=2)
1434 return convert_norep(src, precedence);
1435
1436 std::string dest="POINTER_ARITHMETIC(";
1437
1438 unsigned p;
1439 std::string op;
1440
1441 op = convert(to_binary_expr(src).op0().type());
1442 dest+=op;
1443
1444 dest+=", ";
1445
1446 op = convert_with_precedence(to_binary_expr(src).op0(), p);
1447 if(precedence>p)
1448 dest+='(';
1449 dest+=op;
1450 if(precedence>p)
1451 dest+=')';
1452
1453 dest+=", ";
1454
1455 op = convert_with_precedence(to_binary_expr(src).op1(), p);
1456 if(precedence>p)
1457 dest+='(';
1458 dest+=op;
1459 if(precedence>p)
1460 dest+=')';
1461
1462 dest+=')';
1463
1464 return dest;
1465}
1466
1468 const exprt &src, unsigned &precedence)
1469{
1470 if(src.operands().size()!=2)
1471 return convert_norep(src, precedence);
1472
1473 const auto &binary_expr = to_binary_expr(src);
1474
1475 std::string dest="POINTER_DIFFERENCE(";
1476
1477 unsigned p;
1478 std::string op;
1479
1480 op = convert(binary_expr.op0().type());
1481 dest+=op;
1482
1483 dest+=", ";
1484
1485 op = convert_with_precedence(binary_expr.op0(), p);
1486 if(precedence>p)
1487 dest+='(';
1488 dest+=op;
1489 if(precedence>p)
1490 dest+=')';
1491
1492 dest+=", ";
1493
1494 op = convert_with_precedence(binary_expr.op1(), p);
1495 if(precedence>p)
1496 dest+='(';
1497 dest+=op;
1498 if(precedence>p)
1499 dest+=')';
1500
1501 dest+=')';
1502
1503 return dest;
1504}
1505
1507{
1508 unsigned precedence;
1509
1510 if(!src.operands().empty())
1511 return convert_norep(src, precedence);
1512
1513 return "."+src.get_string(ID_component_name);
1514}
1515
1517{
1518 unsigned precedence;
1519
1520 if(src.operands().size()!=1)
1521 return convert_norep(src, precedence);
1522
1523 return "[" + convert(to_unary_expr(src).op()) + "]";
1524}
1525
1527 const member_exprt &src,
1528 unsigned precedence)
1529{
1530 const auto &compound = src.compound();
1531
1532 unsigned p;
1533 std::string dest;
1534
1535 if(compound.id() == ID_dereference)
1536 {
1537 const auto &pointer = to_dereference_expr(compound).pointer();
1538
1539 std::string op = convert_with_precedence(pointer, p);
1540
1541 if(precedence > p || pointer.id() == ID_typecast)
1542 dest+='(';
1543 dest+=op;
1544 if(precedence > p || pointer.id() == ID_typecast)
1545 dest+=')';
1546
1547 dest+="->";
1548 }
1549 else
1550 {
1551 std::string op = convert_with_precedence(compound, p);
1552
1553 if(precedence > p || compound.id() == ID_typecast)
1554 dest+='(';
1555 dest+=op;
1556 if(precedence > p || compound.id() == ID_typecast)
1557 dest+=')';
1558
1559 dest+='.';
1560 }
1561
1562 if(
1563 compound.type().id() != ID_struct && compound.type().id() != ID_union &&
1564 compound.type().id() != ID_struct_tag &&
1565 compound.type().id() != ID_union_tag)
1566 {
1567 return convert_norep(src, precedence);
1568 }
1569
1571 (compound.type().id() == ID_struct_tag ||
1572 compound.type().id() == ID_union_tag)
1573 ? ns.follow_tag(to_struct_or_union_tag_type(compound.type()))
1574 : to_struct_union_type(compound.type());
1575
1576 irep_idt component_name=src.get_component_name();
1577
1578 if(!component_name.empty())
1579 {
1580 const auto &comp_expr = struct_union_type.get_component(component_name);
1581
1582 if(comp_expr.is_nil())
1583 return convert_norep(src, precedence);
1584
1585 if(!comp_expr.get_pretty_name().empty())
1586 dest += id2string(comp_expr.get_pretty_name());
1587 else
1588 dest+=id2string(component_name);
1589
1590 return dest;
1591 }
1592
1593 std::size_t n=src.get_component_number();
1594
1595 if(n>=struct_union_type.components().size())
1596 return convert_norep(src, precedence);
1597
1598 const auto &comp_expr = struct_union_type.components()[n];
1599
1600 if(!comp_expr.get_pretty_name().empty())
1601 dest += id2string(comp_expr.get_pretty_name());
1602 else
1603 dest += id2string(comp_expr.get_name());
1604
1605 return dest;
1606}
1607
1609 const exprt &src,
1610 unsigned precedence)
1611{
1612 if(src.operands().size()!=1)
1613 return convert_norep(src, precedence);
1614
1615 return "[]=" + convert(to_unary_expr(src).op());
1616}
1617
1619 const exprt &src,
1620 unsigned precedence)
1621{
1622 if(src.operands().size()!=1)
1623 return convert_norep(src, precedence);
1624
1625 return "." + src.get_string(ID_name) + "=" + convert(to_unary_expr(src).op());
1626}
1627
1629 const exprt &src,
1630 unsigned &precedence)
1631{
1633 irep2lisp(src, lisp);
1634 std::string dest="irep(\""+MetaString(lisp.expr2string())+"\")";
1635 precedence=16;
1636 return dest;
1637}
1638
1639std::string expr2ct::convert_symbol(const exprt &src)
1640{
1641 const irep_idt &id=src.get(ID_identifier);
1642 std::string dest;
1643
1644 if(
1645 src.operands().size() == 1 &&
1647 {
1648 dest = to_unary_expr(src).op().get_string(ID_identifier);
1649 }
1650 else
1651 {
1652 std::unordered_map<irep_idt, irep_idt>::const_iterator entry =
1653 shorthands.find(id);
1654 // we might be called from conversion of a type
1655 if(entry==shorthands.end())
1656 {
1657 get_shorthands(src);
1658
1659 entry=shorthands.find(id);
1660 CHECK_RETURN(entry != shorthands.end());
1661 }
1662
1663 dest=id2string(entry->second);
1664
1665 #if 0
1666 if(id.starts_with(SYMEX_DYNAMIC_PREFIX "::dynamic_object"))
1667 {
1668 if(sizeof_nesting++ == 0)
1669 dest+=" /*"+convert(src.type());
1670 if(--sizeof_nesting == 0)
1671 dest+="*/";
1672 }
1673 #endif
1674 }
1675
1676 return dest;
1677}
1678
1680{
1681 const irep_idt id=src.get_identifier();
1682 return "nondet_symbol<" + convert(src.type()) + ">(" + id2string(id) + ")";
1683}
1684
1686{
1687 const std::string &id=src.get_string(ID_identifier);
1688 return "ps("+id+")";
1689}
1690
1692{
1693 const std::string &id=src.get_string(ID_identifier);
1694 return "pns("+id+")";
1695}
1696
1698{
1699 const std::string &id=src.get_string(ID_identifier);
1700 return "pps("+id+")";
1701}
1702
1704{
1705 const std::string &id=src.get_string(ID_identifier);
1706 return id;
1707}
1708
1710{
1711 return "nondet_bool()";
1712}
1713
1715 const exprt &src,
1716 unsigned &precedence)
1717{
1718 if(src.operands().size()!=2)
1719 return convert_norep(src, precedence);
1720
1721 std::string result="<";
1722
1723 result += convert(to_binary_expr(src).op0());
1724 result+=", ";
1725 result += convert(to_binary_expr(src).op1());
1726 result+=", ";
1727
1728 if(src.type().is_nil())
1729 result+='?';
1730 else
1731 result+=convert(src.type());
1732
1733 result+='>';
1734
1735 return result;
1736}
1737
1738static std::optional<exprt>
1740{
1741 const typet &type = static_cast<const typet &>(expr.find(ID_C_c_sizeof_type));
1742
1743 if(type.is_nil())
1744 return {};
1745
1746 const auto type_size_expr = size_of_expr(type, ns);
1747 std::optional<mp_integer> type_size;
1748 if(type_size_expr.has_value())
1750 auto val = numeric_cast<mp_integer>(expr);
1751
1752 if(
1753 !type_size.has_value() || *type_size < 0 || !val.has_value() ||
1754 *val < *type_size || (*type_size == 0 && *val > 0))
1755 {
1756 return {};
1757 }
1758
1759 const unsignedbv_typet t(size_type());
1761 address_bits(*val + 1) <= t.get_width(),
1762 "sizeof value does not fit size_type");
1763
1765
1766 if(*type_size != 0)
1767 {
1768 remainder = *val % *type_size;
1769 *val -= remainder;
1770 *val /= *type_size;
1771 }
1772
1773 exprt result(ID_sizeof, t);
1774 result.set(ID_type_arg, type);
1775
1776 if(*val > 1)
1777 result = mult_exprt(result, from_integer(*val, t));
1778 if(remainder > 0)
1779 result = plus_exprt(result, from_integer(remainder, t));
1780
1781 return typecast_exprt::conditional_cast(result, expr.type());
1782}
1783
1785 const constant_exprt &src,
1786 unsigned &precedence)
1787{
1788 const irep_idt &base=src.get(ID_C_base);
1789 const typet &type = src.type();
1790 const irep_idt value=src.get_value();
1791 std::string dest;
1792
1793 if(type.id()==ID_integer ||
1794 type.id()==ID_natural ||
1795 type.id()==ID_rational)
1796 {
1797 dest=id2string(value);
1798 }
1799 else if(type.id()==ID_c_enum ||
1800 type.id()==ID_c_enum_tag)
1801 {
1803 ? to_c_enum_type(type)
1804 : ns.follow_tag(to_c_enum_tag_type(type));
1805
1806 if(c_enum_type.id()!=ID_c_enum)
1807 return convert_norep(src, precedence);
1808
1809 if(!configuration.print_enum_int_value)
1810 {
1811 const c_enum_typet::memberst &members =
1812 to_c_enum_type(c_enum_type).members();
1813
1814 for(const auto &member : members)
1815 {
1816 if(member.get_value() == value)
1817 return "/*enum*/" + id2string(member.get_base_name());
1818 }
1819 }
1820
1821 // lookup failed or enum is to be output as integer
1822 const bool is_signed = c_enum_type.underlying_type().id() == ID_signedbv;
1823 const auto width =
1824 to_bitvector_type(c_enum_type.underlying_type()).get_width();
1825
1826 std::string value_as_string =
1827 integer2string(bvrep2integer(value, width, is_signed));
1828
1829 if(configuration.print_enum_int_value)
1830 return value_as_string;
1831 else
1832 return "/*enum*/" + value_as_string;
1833 }
1834 else if(type.id()==ID_rational)
1835 return convert_norep(src, precedence);
1836 else if(type.id()==ID_bv)
1837 {
1838 // used for _BitInt
1841 {
1842 auto as_int = bvrep2integer(value, to_bv_type(type).width(), false);
1843 auto width = src.get_int(ID_C_c_bitint_width);
1844 auto binary = integer2binary(as_int, width); // drops padding
1845 return integer2string(binary2integer(binary, true));
1846 }
1847 else if(c_type == ID_c_unsigned_bitint)
1848 {
1849 auto as_int = bvrep2integer(value, to_bv_type(type).width(), false);
1850 auto width = src.get_int(ID_C_c_bitint_width);
1851 auto binary = integer2binary(as_int, width); // drops padding
1852 return integer2string(binary2integer(binary, false));
1853 }
1854 else
1855 return convert_norep(src, precedence);
1856 }
1857 else if(type.id()==ID_bool)
1858 {
1859 dest=convert_constant_bool(src.is_true());
1860 }
1861 else if(type.id()==ID_unsignedbv ||
1862 type.id()==ID_signedbv ||
1863 type.id()==ID_c_bit_field ||
1864 type.id()==ID_c_bool)
1865 {
1866 const auto width = to_bitvector_type(type).get_width();
1867
1869 value,
1870 width,
1871 type.id() == ID_signedbv ||
1872 (type.id() == ID_c_bit_field &&
1873 to_c_bit_field_type(type).underlying_type().id() == ID_signedbv));
1874
1875 const irep_idt &c_type =
1876 type.id() == ID_c_bit_field
1877 ? to_c_bit_field_type(type).underlying_type().get(ID_C_c_type)
1878 : type.get(ID_C_c_type);
1879
1880 if(type.id()==ID_c_bool)
1881 {
1883 }
1884 else if(type==char_type() &&
1885 type!=signed_int_type() &&
1886 type!=unsigned_int_type())
1887 {
1888 if(int_value=='\n')
1889 dest+="'\\n'";
1890 else if(int_value=='\r')
1891 dest+="'\\r'";
1892 else if(int_value=='\t')
1893 dest+="'\\t'";
1894 else if(int_value=='\'')
1895 dest+="'\\''";
1896 else if(int_value=='\\')
1897 dest+="'\\\\'";
1898 else if(int_value>=' ' && int_value<126)
1899 {
1900 dest+='\'';
1902 dest+='\'';
1903 }
1904 else
1906 }
1907 else
1908 {
1909 if(base=="16")
1910 dest="0x"+integer2string(int_value, 16);
1911 else if(base=="8")
1912 dest="0"+integer2string(int_value, 8);
1913 else if(base=="2")
1914 dest="0b"+integer2string(int_value, 2);
1915 else
1917
1919 dest+='u';
1921 dest+="ul";
1922 else if(c_type==ID_signed_long_int)
1923 dest+='l';
1925 dest+="ull";
1927 dest+="ll";
1928
1929 if(sizeof_nesting == 0)
1930 {
1931 const auto sizeof_expr_opt = build_sizeof_expr(src, ns);
1932
1933 if(sizeof_expr_opt.has_value())
1934 {
1936 dest = convert(sizeof_expr_opt.value()) + " /*" + dest + "*/ ";
1938 }
1939 }
1940 }
1941 }
1942 else if(type.id()==ID_floatbv)
1943 {
1945
1946 if(!dest.empty() && isdigit(dest[dest.size() - 1]))
1947 {
1948 if(dest.find('.')==std::string::npos)
1949 dest+=".0";
1950
1951 // ANSI-C: double is default; float/long-double require annotation
1952 if(src.type()==float_type())
1953 dest+='f';
1954 else if(src.type()==long_double_type() &&
1956 dest+='l';
1957 }
1958 else if(dest.size()==4 &&
1959 (dest[0]=='+' || dest[0]=='-'))
1960 {
1961 if(configuration.use_library_macros)
1962 {
1963 if(dest == "+inf")
1964 dest = "+INFINITY";
1965 else if(dest == "-inf")
1966 dest = "-INFINITY";
1967 else if(dest == "+NaN")
1968 dest = "+NAN";
1969 else if(dest == "-NaN")
1970 dest = "-NAN";
1971 }
1972 else
1973 {
1974 // ANSI-C: double is default; float/long-double require annotation
1975 std::string suffix = "";
1976 if(src.type() == float_type())
1977 suffix = "f";
1978 else if(
1979 src.type() == long_double_type() &&
1981 {
1982 suffix = "l";
1983 }
1984
1985 if(dest == "+inf")
1986 dest = "(1.0" + suffix + "/0.0" + suffix + ")";
1987 else if(dest == "-inf")
1988 dest = "(-1.0" + suffix + "/0.0" + suffix + ")";
1989 else if(dest == "+NaN")
1990 dest = "(0.0" + suffix + "/0.0" + suffix + ")";
1991 else if(dest == "-NaN")
1992 dest = "(-0.0" + suffix + "/0.0" + suffix + ")";
1993 }
1994 }
1995 }
1996 else if(type.id()==ID_fixedbv)
1997 {
1999
2000 if(!dest.empty() && isdigit(dest[dest.size() - 1]))
2001 {
2002 if(src.type()==float_type())
2003 dest+='f';
2004 else if(src.type()==long_double_type())
2005 dest+='l';
2006 }
2007 }
2008 else if(type.id() == ID_array)
2009 {
2010 dest = convert_array(src);
2011 }
2012 else if(type.id()==ID_pointer)
2013 {
2014 if(src.is_null_pointer())
2015 {
2016 if(configuration.use_library_macros)
2017 dest = "NULL";
2018 else
2019 dest = "0";
2020 if(to_pointer_type(type).base_type().id() != ID_empty)
2021 dest="(("+convert(type)+")"+dest+")";
2022 }
2023 else if(
2024 value == "INVALID" || value.starts_with("INVALID-") ||
2025 value == "NULL+offset")
2026 {
2027 dest = id2string(value);
2028 }
2029 else
2030 {
2031 const auto width = to_pointer_type(type).get_width();
2032 mp_integer int_value = bvrep2integer(value, width, false);
2033 return "(" + convert(type) + ")" + integer2string(int_value);
2034 }
2035 }
2036 else if(type.id()==ID_string)
2037 {
2038 return '"'+id2string(src.get_value())+'"';
2039 }
2040 else
2041 return convert_norep(src, precedence);
2042
2043 return dest;
2044}
2045
2048 unsigned &precedence)
2049{
2050 const auto &annotation = src.symbolic_pointer();
2051
2052 return convert_with_precedence(annotation, precedence);
2053}
2054
2060{
2061 if(boolean_value)
2062 return configuration.true_string;
2063 else
2064 return configuration.false_string;
2065}
2066
2068 const exprt &src,
2069 unsigned &precedence)
2070{
2071 return convert_struct(
2072 src, precedence, configuration.include_struct_padding_components);
2073}
2074
2084 const exprt &src,
2085 unsigned &precedence,
2087{
2088 if(src.type().id() != ID_struct && src.type().id() != ID_struct_tag)
2089 return convert_norep(src, precedence);
2090
2091 const struct_typet &struct_type =
2092 src.type().id() == ID_struct_tag
2093 ? ns.follow_tag(to_struct_tag_type(src.type()))
2094 : to_struct_type(src.type());
2095
2096 const struct_typet::componentst &components=
2097 struct_type.components();
2098
2099 if(components.size()!=src.operands().size())
2100 return convert_norep(src, precedence);
2101
2102 std::string dest="{ ";
2103
2104 exprt::operandst::const_iterator o_it=src.operands().begin();
2105
2106 bool first=true;
2107 bool newline=false;
2108 size_t last_size=0;
2109
2110 for(const auto &component : struct_type.components())
2111 {
2113 o_it->type().id() != ID_code, "struct member must not be of code type");
2114
2115 if(component.get_is_padding() && !include_padding_components)
2116 {
2117 ++o_it;
2118 continue;
2119 }
2120
2121 if(first)
2122 first=false;
2123 else
2124 {
2125 dest+=',';
2126
2127 if(newline)
2128 dest+="\n ";
2129 else
2130 dest+=' ';
2131 }
2132
2133 std::string tmp=convert(*o_it);
2134
2135 if(last_size+40<dest.size())
2136 {
2137 newline=true;
2138 last_size=dest.size();
2139 }
2140 else
2141 newline=false;
2142
2143 dest+='.';
2144 dest+=component.get_string(ID_name);
2145 dest+='=';
2146 dest+=tmp;
2147
2148 o_it++;
2149 }
2150
2151 dest+=" }";
2152
2153 return dest;
2154}
2155
2157 const exprt &src,
2158 unsigned &precedence)
2159{
2160 const typet &type = src.type();
2161
2162 if(type.id() != ID_vector)
2163 return convert_norep(src, precedence);
2164
2165 std::string dest="{ ";
2166
2167 bool first=true;
2168 bool newline=false;
2169 size_t last_size=0;
2170
2171 for(const auto &op : src.operands())
2172 {
2173 if(first)
2174 first=false;
2175 else
2176 {
2177 dest+=',';
2178
2179 if(newline)
2180 dest+="\n ";
2181 else
2182 dest+=' ';
2183 }
2184
2185 std::string tmp = convert(op);
2186
2187 if(last_size+40<dest.size())
2188 {
2189 newline=true;
2190 last_size=dest.size();
2191 }
2192 else
2193 newline=false;
2194
2195 dest+=tmp;
2196 }
2197
2198 dest+=" }";
2199
2200 return dest;
2201}
2202
2204 const exprt &src,
2205 unsigned &precedence)
2206{
2207 std::string dest="{ ";
2208
2209 if(src.operands().size()!=1)
2210 return convert_norep(src, precedence);
2211
2212 dest+='.';
2213 dest+=src.get_string(ID_component_name);
2214 dest+='=';
2215 dest += convert(to_union_expr(src).op());
2216
2217 dest+=" }";
2218
2219 return dest;
2220}
2221
2222std::string expr2ct::convert_array(const exprt &src)
2223{
2224 std::string dest;
2225
2226 // we treat arrays of characters as string constants,
2227 // and arrays of wchar_t as wide strings
2228
2229 const typet &element_type = to_array_type(src.type()).element_type();
2230
2231 bool all_constant=true;
2232
2233 for(const auto &op : src.operands())
2234 {
2235 if(!op.is_constant())
2236 all_constant=false;
2237 }
2238
2239 if(
2241 (element_type == char_type() || element_type == wchar_t_type()))
2242 {
2243 bool wide = element_type == wchar_t_type();
2244
2245 if(wide)
2246 dest+='L';
2247
2248 dest+="\"";
2249
2250 dest.reserve(dest.size()+1+src.operands().size());
2251
2252 bool last_was_hex=false;
2253
2254 forall_operands(it, src)
2255 {
2256 // these have a trailing zero
2257 if(it==--src.operands().end())
2258 break;
2259
2260 const unsigned int ch = numeric_cast_v<unsigned>(to_constant_expr(*it));
2261
2262 if(last_was_hex)
2263 {
2264 // we use "string splicing" to avoid ambiguity
2265 if(isxdigit(ch))
2266 dest+="\" \"";
2267
2268 last_was_hex=false;
2269 }
2270
2271 switch(ch)
2272 {
2273 case '\n': dest+="\\n"; break; /* NL (0x0a) */
2274 case '\t': dest+="\\t"; break; /* HT (0x09) */
2275 case '\v': dest+="\\v"; break; /* VT (0x0b) */
2276 case '\b': dest+="\\b"; break; /* BS (0x08) */
2277 case '\r': dest+="\\r"; break; /* CR (0x0d) */
2278 case '\f': dest+="\\f"; break; /* FF (0x0c) */
2279 case '\a': dest+="\\a"; break; /* BEL (0x07) */
2280 case '\\': dest+="\\\\"; break;
2281 case '"': dest+="\\\""; break;
2282
2283 default:
2284 if(ch>=' ' && ch!=127 && ch<0xff)
2285 dest+=static_cast<char>(ch);
2286 else
2287 {
2288 std::ostringstream oss;
2289 oss << "\\x" << std::hex << ch;
2290 dest += oss.str();
2291 last_was_hex=true;
2292 }
2293 }
2294 }
2295
2296 dest+="\"";
2297
2298 return dest;
2299 }
2300
2301 dest="{ ";
2302
2303 forall_operands(it, src)
2304 {
2305 std::string tmp;
2306
2307 if(it->is_not_nil())
2308 tmp=convert(*it);
2309
2310 if((it+1)!=src.operands().end())
2311 {
2312 tmp+=", ";
2313 if(tmp.size()>40)
2314 tmp+="\n ";
2315 }
2316
2317 dest+=tmp;
2318 }
2319
2320 dest+=" }";
2321
2322 return dest;
2323}
2324
2326 const exprt &src,
2327 unsigned &precedence)
2328{
2329 std::string dest="{ ";
2330
2331 if((src.operands().size()%2)!=0)
2332 return convert_norep(src, precedence);
2333
2334 forall_operands(it, src)
2335 {
2336 std::string tmp1=convert(*it);
2337
2338 it++;
2339
2340 std::string tmp2=convert(*it);
2341
2342 std::string tmp="["+tmp1+"]="+tmp2;
2343
2344 if((it+1)!=src.operands().end())
2345 {
2346 tmp+=", ";
2347 if(tmp.size()>40)
2348 tmp+="\n ";
2349 }
2350
2351 dest+=tmp;
2352 }
2353
2354 dest+=" }";
2355
2356 return dest;
2357}
2358
2360{
2361 std::string dest;
2362 if(src.id()!=ID_compound_literal)
2363 dest+="{ ";
2364
2365 forall_operands(it, src)
2366 {
2367 std::string tmp=convert(*it);
2368
2369 if((it+1)!=src.operands().end())
2370 {
2371 tmp+=", ";
2372 if(tmp.size()>40)
2373 tmp+="\n ";
2374 }
2375
2376 dest+=tmp;
2377 }
2378
2379 if(src.id()!=ID_compound_literal)
2380 dest+=" }";
2381
2382 return dest;
2383}
2384
2385std::string expr2ct::convert_rox(const shift_exprt &src, unsigned precedence)
2386{
2387 // AAAA rox n == (AAAA lhs_op n % width(AAAA))
2388 // | (AAAA rhs_op (width(AAAA) - n % width(AAAA)))
2389 // Where lhs_op and rhs_op depend on whether it is rol or ror
2390 // Get AAAA and if it's signed wrap it in a cast to remove
2391 // the sign since this messes with C shifts
2392 exprt op0 = src.op();
2393 size_t type_width;
2395 {
2396 // Set the type width
2397 type_width = to_signedbv_type(op0.type()).get_width();
2398 // Shifts in C are arithmetic and care about sign, by forcing
2399 // a cast to unsigned we force the shifts to perform rol/r
2401 }
2403 {
2404 // Set the type width
2405 type_width = to_unsignedbv_type(op0.type()).get_width();
2406 }
2407 else
2408 {
2410 }
2411 // Construct the "width(AAAA)" constant
2413 // Apply modulo to n since shifting will overflow
2414 // That is: 0001 << 4 == 0, but 0001 rol 4 == 0001
2416 // Now put the pieces together
2417 // width(AAAA) - (n % width(AAAA))
2418 const auto complement_width_expr =
2420 // lhs and rhs components defined according to rol/ror
2423 if(src.id() == ID_rol)
2424 {
2425 // AAAA << (n % width(AAAA))
2427 // AAAA >> complement_width_expr
2429 }
2430 else if(src.id() == ID_ror)
2431 {
2432 // AAAA >> (n % width(AAAA))
2434 // AAAA << complement_width_expr
2436 }
2437 else
2438 {
2439 // Someone called this function when they shouldn't have.
2441 }
2443}
2444
2446{
2447 if(src.operands().size()!=1)
2448 {
2449 unsigned precedence;
2450 return convert_norep(src, precedence);
2451 }
2452
2453 const exprt &value = to_unary_expr(src).op();
2454
2455 const exprt &designator = static_cast<const exprt &>(src.find(ID_designator));
2456 if(designator.operands().size() != 1)
2457 {
2458 unsigned precedence;
2459 return convert_norep(src, precedence);
2460 }
2461
2462 const exprt &designator_id = to_unary_expr(designator).op();
2463
2464 std::string dest;
2465
2466 if(designator_id.id() == ID_member)
2467 {
2468 dest = "." + id2string(designator_id.get(ID_component_name));
2469 }
2470 else if(
2471 designator_id.id() == ID_index && designator_id.operands().size() == 1)
2472 {
2473 dest = "[" + convert(to_unary_expr(designator_id).op()) + "]";
2474 }
2475 else
2476 {
2477 unsigned precedence;
2478 return convert_norep(src, precedence);
2479 }
2480
2481 dest+='=';
2482 dest += convert(value);
2483
2484 return dest;
2485}
2486
2487std::string
2489{
2490 std::string dest;
2491
2492 {
2493 unsigned p;
2494 std::string function_str=convert_with_precedence(src.function(), p);
2495 dest+=function_str;
2496 }
2497
2498 dest+='(';
2499
2500 forall_expr(it, src.arguments())
2501 {
2502 unsigned p;
2503 std::string arg_str=convert_with_precedence(*it, p);
2504
2505 if(it!=src.arguments().begin())
2506 dest+=", ";
2507 // TODO: ggf. Klammern je nach p
2508 dest+=arg_str;
2509 }
2510
2511 dest+=')';
2512
2513 return dest;
2514}
2515
2518{
2519 std::string dest;
2520
2521 {
2522 unsigned p;
2523 std::string function_str=convert_with_precedence(src.function(), p);
2524 dest+=function_str;
2525 }
2526
2527 dest+='(';
2528
2529 forall_expr(it, src.arguments())
2530 {
2531 unsigned p;
2532 std::string arg_str=convert_with_precedence(*it, p);
2533
2534 if(it!=src.arguments().begin())
2535 dest+=", ";
2536 // TODO: ggf. Klammern je nach p
2537 dest+=arg_str;
2538 }
2539
2540 dest+=')';
2541
2542 return dest;
2543}
2544
2546 const exprt &src,
2547 unsigned &precedence)
2548{
2549 precedence=16;
2550
2551 std::string dest="overflow(\"";
2552 dest+=src.id().c_str()+9;
2553 dest+="\"";
2554
2555 if(!src.operands().empty())
2556 {
2557 dest+=", ";
2558 dest += convert(to_multi_ary_expr(src).op0().type());
2559 }
2560
2561 for(const auto &op : src.operands())
2562 {
2563 unsigned p;
2564 std::string arg_str = convert_with_precedence(op, p);
2565
2566 dest+=", ";
2567 // TODO: ggf. Klammern je nach p
2568 dest+=arg_str;
2569 }
2570
2571 dest+=')';
2572
2573 return dest;
2574}
2575
2576std::string expr2ct::indent_str(unsigned indent)
2577{
2578 return std::string(indent, ' ');
2579}
2580
2582 const code_asmt &src,
2583 unsigned indent)
2584{
2585 std::string dest=indent_str(indent);
2586
2587 if(src.get_flavor()==ID_gcc)
2588 {
2589 if(src.operands().size()==5)
2590 {
2591 dest+="asm(";
2592 dest+=convert(src.op0());
2593 if(!src.operands()[1].operands().empty() ||
2594 !src.operands()[2].operands().empty() ||
2595 !src.operands()[3].operands().empty() ||
2596 !src.operands()[4].operands().empty())
2597 {
2598 // need extended syntax
2599
2600 // outputs
2601 dest+=" : ";
2602 forall_operands(it, src.op1())
2603 {
2604 if(it->operands().size()==2)
2605 {
2606 if(it!=src.op1().operands().begin())
2607 dest+=", ";
2608 dest += convert(to_binary_expr(*it).op0());
2609 dest+="(";
2610 dest += convert(to_binary_expr(*it).op1());
2611 dest+=")";
2612 }
2613 }
2614
2615 // inputs
2616 dest+=" : ";
2617 forall_operands(it, src.op2())
2618 {
2619 if(it->operands().size()==2)
2620 {
2621 if(it!=src.op2().operands().begin())
2622 dest+=", ";
2623 dest += convert(to_binary_expr(*it).op0());
2624 dest+="(";
2625 dest += convert(to_binary_expr(*it).op1());
2626 dest+=")";
2627 }
2628 }
2629
2630 // clobbered registers
2631 dest+=" : ";
2632 forall_operands(it, src.op3())
2633 {
2634 if(it!=src.op3().operands().begin())
2635 dest+=", ";
2636 if(it->id()==ID_gcc_asm_clobbered_register)
2637 dest += convert(to_unary_expr(*it).op());
2638 else
2639 dest+=convert(*it);
2640 }
2641 }
2642 dest+=");";
2643 }
2644 }
2645 else if(src.get_flavor()==ID_msc)
2646 {
2647 if(src.operands().size()==1)
2648 {
2649 dest+="__asm {\n";
2650 dest+=indent_str(indent);
2651 dest+=convert(src.op0());
2652 dest+="\n}";
2653 }
2654 }
2655
2656 return dest;
2657}
2658
2660 const code_whilet &src,
2661 unsigned indent)
2662{
2663 if(src.operands().size()!=2)
2664 {
2665 unsigned precedence;
2666 return convert_norep(src, precedence);
2667 }
2668
2669 std::string dest=indent_str(indent);
2670 dest+="while("+convert(src.cond());
2671
2672 if(src.body().is_nil())
2673 dest+=");";
2674 else
2675 {
2676 dest+=")\n";
2677 dest+=convert_code(
2678 src.body(),
2679 src.body().get_statement()==ID_block ? indent : indent+2);
2680 }
2681
2682 return dest;
2683}
2684
2686 const code_dowhilet &src,
2687 unsigned indent)
2688{
2689 if(src.operands().size()!=2)
2690 {
2691 unsigned precedence;
2692 return convert_norep(src, precedence);
2693 }
2694
2695 std::string dest=indent_str(indent);
2696
2697 if(src.body().is_nil())
2698 dest+="do;";
2699 else
2700 {
2701 dest+="do\n";
2702 dest+=convert_code(
2703 src.body(),
2704 src.body().get_statement()==ID_block ? indent : indent+2);
2705 dest+="\n";
2706 dest+=indent_str(indent);
2707 }
2708
2709 dest+="while("+convert(src.cond())+");";
2710
2711 return dest;
2712}
2713
2715 const code_ifthenelset &src,
2716 unsigned indent)
2717{
2718 if(src.operands().size()!=3)
2719 {
2720 unsigned precedence;
2721 return convert_norep(src, precedence);
2722 }
2723
2724 std::string dest=indent_str(indent);
2725 dest+="if("+convert(src.cond())+")\n";
2726
2727 if(src.then_case().is_nil())
2728 {
2729 dest+=indent_str(indent+2);
2730 dest+=';';
2731 }
2732 else
2733 dest += convert_code(
2734 src.then_case(),
2735 src.then_case().get_statement() == ID_block ? indent : indent + 2);
2736 dest+="\n";
2737
2738 if(!src.else_case().is_nil())
2739 {
2740 dest+="\n";
2741 dest+=indent_str(indent);
2742 dest+="else\n";
2743 dest += convert_code(
2744 src.else_case(),
2745 src.else_case().get_statement() == ID_block ? indent : indent + 2);
2746 }
2747
2748 return dest;
2749}
2750
2752 const codet &src,
2753 unsigned indent)
2754{
2755 if(src.operands().size() != 1)
2756 {
2757 unsigned precedence;
2758 return convert_norep(src, precedence);
2759 }
2760
2761 std::string dest=indent_str(indent);
2762 dest+="return";
2763
2764 if(to_code_frontend_return(src).has_return_value())
2765 dest+=" "+convert(src.op0());
2766
2767 dest+=';';
2768
2769 return dest;
2770}
2771
2773 const codet &src,
2774 unsigned indent)
2775{
2776 std:: string dest=indent_str(indent);
2777 dest+="goto ";
2779 dest+=';';
2780
2781 return dest;
2782}
2783
2784std::string expr2ct::convert_code_break(unsigned indent)
2785{
2786 std::string dest=indent_str(indent);
2787 dest+="break";
2788 dest+=';';
2789
2790 return dest;
2791}
2792
2794 const codet &src,
2795 unsigned indent)
2796{
2797 if(src.operands().empty())
2798 {
2799 unsigned precedence;
2800 return convert_norep(src, precedence);
2801 }
2802
2803 std::string dest=indent_str(indent);
2804 dest+="switch(";
2805 dest+=convert(src.op0());
2806 dest+=")\n";
2807
2808 dest+=indent_str(indent);
2809 dest+='{';
2810
2811 forall_operands(it, src)
2812 {
2813 if(it==src.operands().begin())
2814 continue;
2815 const exprt &op=*it;
2816
2817 if(op.get(ID_statement)!=ID_block)
2818 {
2819 unsigned precedence;
2820 dest+=convert_norep(op, precedence);
2821 }
2822 else
2823 {
2824 for(const auto &operand : op.operands())
2825 dest += convert_code(to_code(operand), indent + 2);
2826 }
2827 }
2828
2829 dest+="\n";
2830 dest+=indent_str(indent);
2831 dest+='}';
2832
2833 return dest;
2834}
2835
2836std::string expr2ct::convert_code_continue(unsigned indent)
2837{
2838 std::string dest=indent_str(indent);
2839 dest+="continue";
2840 dest+=';';
2841
2842 return dest;
2843}
2844
2845std::string
2846expr2ct::convert_code_frontend_decl(const codet &src, unsigned indent)
2847{
2848 // initializer to go away
2849 if(src.operands().size()!=1 &&
2850 src.operands().size()!=2)
2851 {
2852 unsigned precedence;
2853 return convert_norep(src, precedence);
2854 }
2855
2856 std::string declarator=convert(src.op0());
2857
2858 std::string dest=indent_str(indent);
2859
2860 const symbolt *symbol=nullptr;
2861 if(!ns.lookup(to_symbol_expr(src.op0()).get_identifier(), symbol))
2862 {
2863 if(symbol->is_file_local &&
2864 (src.op0().type().id()==ID_code || symbol->is_static_lifetime))
2865 dest+="static ";
2866 else if(symbol->is_extern)
2867 dest+="extern ";
2868 else if(
2870 {
2871 dest += "__declspec(dllexport) ";
2872 }
2873
2874 if(symbol->type.id()==ID_code &&
2875 to_code_type(symbol->type).get_inlined())
2876 dest+="inline ";
2877 }
2878
2879 dest += convert_with_identifier(src.op0().type(), declarator);
2880
2881 if(src.operands().size()==2)
2882 dest+="="+convert(src.op1());
2883
2884 dest+=';';
2885
2886 return dest;
2887}
2888
2890 const codet &src,
2891 unsigned indent)
2892{
2893 // initializer to go away
2894 if(src.operands().size()!=1)
2895 {
2896 unsigned precedence;
2897 return convert_norep(src, precedence);
2898 }
2899
2900 return indent_str(indent) + "dead " + convert(src.op0()) + ";";
2901}
2902
2904 const code_fort &src,
2905 unsigned indent)
2906{
2907 if(src.operands().size()!=4)
2908 {
2909 unsigned precedence;
2910 return convert_norep(src, precedence);
2911 }
2912
2913 std::string dest=indent_str(indent);
2914 dest+="for(";
2915
2916 if(!src.init().is_nil())
2917 dest += convert(src.init());
2918 else
2919 dest+=' ';
2920 dest+="; ";
2921 if(!src.cond().is_nil())
2922 dest += convert(src.cond());
2923 dest+="; ";
2924 if(!src.iter().is_nil())
2925 dest += convert(src.iter());
2926
2927 if(src.body().is_nil())
2928 dest+=");\n";
2929 else
2930 {
2931 dest+=")\n";
2932 dest+=convert_code(
2933 src.body(),
2934 src.body().get_statement()==ID_block ? indent : indent+2);
2935 }
2936
2937 return dest;
2938}
2939
2941 const code_blockt &src,
2942 unsigned indent)
2943{
2944 std::string dest=indent_str(indent);
2945 dest+="{\n";
2946
2947 for(const auto &statement : src.statements())
2948 {
2949 if(statement.get_statement() == ID_label)
2950 dest += convert_code(statement, indent);
2951 else
2952 dest += convert_code(statement, indent + 2);
2953
2954 dest+="\n";
2955 }
2956
2957 dest+=indent_str(indent);
2958 dest+='}';
2959
2960 return dest;
2961}
2962
2964 const codet &src,
2965 unsigned indent)
2966{
2967 std::string dest;
2968
2969 for(const auto &op : src.operands())
2970 {
2971 dest += convert_code(to_code(op), indent);
2972 dest+="\n";
2973 }
2974
2975 return dest;
2976}
2977
2979 const codet &src,
2980 unsigned indent)
2981{
2982 std::string dest=indent_str(indent);
2983
2984 std::string expr_str;
2985 if(src.operands().size()==1)
2986 expr_str=convert(src.op0());
2987 else
2988 {
2989 unsigned precedence;
2991 }
2992
2993 dest+=expr_str;
2994 if(dest.empty() || *dest.rbegin()!=';')
2995 dest+=';';
2996
2997 return dest;
2998}
2999
3001 const codet &src,
3002 unsigned indent)
3003{
3004 static bool comment_done=false;
3005
3006 if(
3007 !comment_done && (!src.source_location().get_comment().empty() ||
3008 !src.source_location().get_pragmas().empty()))
3009 {
3010 comment_done=true;
3011 std::string dest;
3012 if(!src.source_location().get_comment().empty())
3013 {
3014 dest += indent_str(indent);
3015 dest += "/* " + id2string(src.source_location().get_comment()) + " */\n";
3016 }
3017 if(!src.source_location().get_pragmas().empty())
3018 {
3019 std::ostringstream oss;
3020 oss << indent_str(indent) << "/* ";
3021 const auto &pragmas = src.source_location().get_pragmas();
3023 oss,
3024 pragmas.begin(),
3025 pragmas.end(),
3026 ',',
3027 [](const std::pair<irep_idt, irept> &p) { return p.first; });
3028 oss << " */\n";
3029 dest += oss.str();
3030 }
3031 dest+=convert_code(src, indent);
3032 comment_done=false;
3033 return dest;
3034 }
3035
3036 const irep_idt &statement=src.get_statement();
3037
3038 if(statement==ID_expression)
3039 return convert_code_expression(src, indent);
3040
3041 if(statement==ID_block)
3042 return convert_code_block(to_code_block(src), indent);
3043
3044 if(statement==ID_switch)
3045 return convert_code_switch(src, indent);
3046
3047 if(statement==ID_for)
3048 return convert_code_for(to_code_for(src), indent);
3049
3050 if(statement==ID_while)
3051 return convert_code_while(to_code_while(src), indent);
3052
3053 if(statement==ID_asm)
3054 return convert_code_asm(to_code_asm(src), indent);
3055
3056 if(statement==ID_skip)
3057 return indent_str(indent)+";";
3058
3059 if(statement==ID_dowhile)
3060 return convert_code_dowhile(to_code_dowhile(src), indent);
3061
3062 if(statement==ID_ifthenelse)
3063 return convert_code_ifthenelse(to_code_ifthenelse(src), indent);
3064
3065 if(statement==ID_return)
3066 return convert_code_return(src, indent);
3067
3068 if(statement==ID_goto)
3069 return convert_code_goto(src, indent);
3070
3071 if(statement==ID_printf)
3072 return convert_code_printf(src, indent);
3073
3074 if(statement==ID_fence)
3075 return convert_code_fence(src, indent);
3076
3078 return convert_code_input(src, indent);
3079
3081 return convert_code_output(src, indent);
3082
3083 if(statement==ID_assume)
3084 return convert_code_assume(src, indent);
3085
3086 if(statement==ID_assert)
3087 return convert_code_assert(src, indent);
3088
3089 if(statement==ID_break)
3090 return convert_code_break(indent);
3091
3092 if(statement==ID_continue)
3093 return convert_code_continue(indent);
3094
3095 if(statement==ID_decl)
3096 return convert_code_frontend_decl(src, indent);
3097
3098 if(statement==ID_decl_block)
3099 return convert_code_decl_block(src, indent);
3100
3101 if(statement==ID_dead)
3102 return convert_code_dead(src, indent);
3103
3104 if(statement==ID_assign)
3106
3107 if(statement=="lock")
3108 return convert_code_lock(src, indent);
3109
3110 if(statement=="unlock")
3111 return convert_code_unlock(src, indent);
3112
3113 if(statement==ID_atomic_begin)
3114 return indent_str(indent) + CPROVER_PREFIX + "atomic_begin();";
3115
3116 if(statement==ID_atomic_end)
3117 return indent_str(indent) + CPROVER_PREFIX + "atomic_end();";
3118
3119 if(statement==ID_function_call)
3121
3122 if(statement==ID_label)
3123 return convert_code_label(to_code_label(src), indent);
3124
3125 if(statement==ID_switch_case)
3126 return convert_code_switch_case(to_code_switch_case(src), indent);
3127
3128 if(statement==ID_array_set)
3129 return convert_code_array_set(src, indent);
3130
3131 if(statement==ID_array_copy)
3132 return convert_code_array_copy(src, indent);
3133
3134 if(statement==ID_array_replace)
3135 return convert_code_array_replace(src, indent);
3136
3137 if(statement == ID_set_may || statement == ID_set_must)
3138 return indent_str(indent) + convert_function(src, id2string(statement)) +
3139 ";";
3140
3141 unsigned precedence;
3142 return convert_norep(src, precedence);
3143}
3144
3146 const code_frontend_assignt &src,
3147 unsigned indent)
3148{
3149 return indent_str(indent) +
3150 convert_binary(to_binary_expr(src), "=", 2, true) + ";";
3151}
3152
3154 const codet &src,
3155 unsigned indent)
3156{
3157 if(src.operands().size()!=1)
3158 {
3159 unsigned precedence;
3160 return convert_norep(src, precedence);
3161 }
3162
3163 return indent_str(indent)+"LOCK("+convert(src.op0())+");";
3164}
3165
3167 const codet &src,
3168 unsigned indent)
3169{
3170 if(src.operands().size()!=1)
3171 {
3172 unsigned precedence;
3173 return convert_norep(src, precedence);
3174 }
3175
3176 return indent_str(indent)+"UNLOCK("+convert(src.op0())+");";
3177}
3178
3180 const code_function_callt &src,
3181 unsigned indent)
3182{
3183 if(src.operands().size()!=3)
3184 {
3185 unsigned precedence;
3186 return convert_norep(src, precedence);
3187 }
3188
3189 std::string dest=indent_str(indent);
3190
3191 if(src.lhs().is_not_nil())
3192 {
3193 unsigned p;
3194 std::string lhs_str=convert_with_precedence(src.lhs(), p);
3195
3196 // TODO: ggf. Klammern je nach p
3197 dest+=lhs_str;
3198 dest+='=';
3199 }
3200
3201 {
3202 unsigned p;
3203 std::string function_str=convert_with_precedence(src.function(), p);
3204 dest+=function_str;
3205 }
3206
3207 dest+='(';
3208
3209 const exprt::operandst &arguments=src.arguments();
3210
3211 forall_expr(it, arguments)
3212 {
3213 unsigned p;
3214 std::string arg_str=convert_with_precedence(*it, p);
3215
3216 if(it!=arguments.begin())
3217 dest+=", ";
3218 // TODO: ggf. Klammern je nach p
3219 dest+=arg_str;
3220 }
3221
3222 dest+=");";
3223
3224 return dest;
3225}
3226
3228 const codet &src,
3229 unsigned indent)
3230{
3231 std::string dest=indent_str(indent)+"printf(";
3232
3233 forall_operands(it, src)
3234 {
3235 unsigned p;
3236 std::string arg_str=convert_with_precedence(*it, p);
3237
3238 if(it!=src.operands().begin())
3239 dest+=", ";
3240 // TODO: ggf. Klammern je nach p
3241 dest+=arg_str;
3242 }
3243
3244 dest+=");";
3245
3246 return dest;
3247}
3248
3250 const codet &src,
3251 unsigned indent)
3252{
3253 std::string dest=indent_str(indent)+"FENCE(";
3254
3255 irep_idt att[]=
3258 irep_idt() };
3259
3260 bool first=true;
3261
3262 for(unsigned i=0; !att[i].empty(); i++)
3263 {
3264 if(src.get_bool(att[i]))
3265 {
3266 if(first)
3267 first=false;
3268 else
3269 dest+='+';
3270
3271 dest+=id2string(att[i]);
3272 }
3273 }
3274
3275 dest+=");";
3276 return dest;
3277}
3278
3280 const codet &src,
3281 unsigned indent)
3282{
3283 std::string dest=indent_str(indent)+"INPUT(";
3284
3285 forall_operands(it, src)
3286 {
3287 unsigned p;
3288 std::string arg_str=convert_with_precedence(*it, p);
3289
3290 if(it!=src.operands().begin())
3291 dest+=", ";
3292 // TODO: ggf. Klammern je nach p
3293 dest+=arg_str;
3294 }
3295
3296 dest+=");";
3297
3298 return dest;
3299}
3300
3302 const codet &src,
3303 unsigned indent)
3304{
3305 std::string dest=indent_str(indent)+"OUTPUT(";
3306
3307 forall_operands(it, src)
3308 {
3309 unsigned p;
3310 std::string arg_str=convert_with_precedence(*it, p);
3311
3312 if(it!=src.operands().begin())
3313 dest+=", ";
3314 dest+=arg_str;
3315 }
3316
3317 dest+=");";
3318
3319 return dest;
3320}
3321
3323 const codet &src,
3324 unsigned indent)
3325{
3326 std::string dest=indent_str(indent)+"ARRAY_SET(";
3327
3328 forall_operands(it, src)
3329 {
3330 unsigned p;
3331 std::string arg_str=convert_with_precedence(*it, p);
3332
3333 if(it!=src.operands().begin())
3334 dest+=", ";
3335 // TODO: ggf. Klammern je nach p
3336 dest+=arg_str;
3337 }
3338
3339 dest+=");";
3340
3341 return dest;
3342}
3343
3345 const codet &src,
3346 unsigned indent)
3347{
3348 std::string dest=indent_str(indent)+"ARRAY_COPY(";
3349
3350 forall_operands(it, src)
3351 {
3352 unsigned p;
3353 std::string arg_str=convert_with_precedence(*it, p);
3354
3355 if(it!=src.operands().begin())
3356 dest+=", ";
3357 // TODO: ggf. Klammern je nach p
3358 dest+=arg_str;
3359 }
3360
3361 dest+=");";
3362
3363 return dest;
3364}
3365
3367 const codet &src,
3368 unsigned indent)
3369{
3370 std::string dest=indent_str(indent)+"ARRAY_REPLACE(";
3371
3372 forall_operands(it, src)
3373 {
3374 unsigned p;
3375 std::string arg_str=convert_with_precedence(*it, p);
3376
3377 if(it!=src.operands().begin())
3378 dest+=", ";
3379 dest+=arg_str;
3380 }
3381
3382 dest+=");";
3383
3384 return dest;
3385}
3386
3388 const codet &src,
3389 unsigned indent)
3390{
3391 if(src.operands().size()!=1)
3392 {
3393 unsigned precedence;
3394 return convert_norep(src, precedence);
3395 }
3396
3397 return indent_str(indent)+"assert("+convert(src.op0())+");";
3398}
3399
3401 const codet &src,
3402 unsigned indent)
3403{
3404 if(src.operands().size()!=1)
3405 {
3406 unsigned precedence;
3407 return convert_norep(src, precedence);
3408 }
3409
3410 return indent_str(indent) + CPROVER_PREFIX + "assume(" + convert(src.op0()) +
3411 ");";
3412}
3413
3415 const code_labelt &src,
3416 unsigned indent)
3417{
3418 std::string labels_string;
3419
3420 irep_idt label=src.get_label();
3421
3422 labels_string+="\n";
3423 labels_string+=indent_str(indent);
3425 labels_string+=":\n";
3426
3427 std::string tmp=convert_code(src.code(), indent+2);
3428
3429 return labels_string+tmp;
3430}
3431
3433 const code_switch_caset &src,
3434 unsigned indent)
3435{
3436 std::string labels_string;
3437
3438 if(src.is_default())
3439 {
3440 labels_string+="\n";
3441 labels_string+=indent_str(indent);
3442 labels_string+="default:\n";
3443 }
3444 else
3445 {
3446 labels_string+="\n";
3447 labels_string+=indent_str(indent);
3448 labels_string+="case ";
3450 labels_string+=":\n";
3451 }
3452
3453 unsigned next_indent=indent;
3454 if(src.code().get_statement()!=ID_block &&
3456 next_indent+=2;
3457 std::string tmp=convert_code(src.code(), next_indent);
3458
3459 return labels_string+tmp;
3460}
3461
3462std::string expr2ct::convert_code(const codet &src)
3463{
3464 return convert_code(src, 0);
3465}
3466
3467std::string expr2ct::convert_Hoare(const exprt &src)
3468{
3469 unsigned precedence;
3470
3471 if(src.operands().size()!=2)
3472 return convert_norep(src, precedence);
3473
3474 const exprt &assumption = to_binary_expr(src).op0();
3475 const exprt &assertion = to_binary_expr(src).op1();
3476 const codet &code=
3477 static_cast<const codet &>(src.find(ID_code));
3478
3479 std::string dest="\n";
3480 dest+='{';
3481
3482 if(!assumption.is_nil())
3483 {
3484 std::string assumption_str=convert(assumption);
3485 dest+=" assume(";
3486 dest+=assumption_str;
3487 dest+=");\n";
3488 }
3489 else
3490 dest+="\n";
3491
3492 {
3493 std::string code_str=convert_code(code);
3494 dest+=code_str;
3495 }
3496
3497 if(!assertion.is_nil())
3498 {
3499 std::string assertion_str=convert(assertion);
3500 dest+=" assert(";
3501 dest+=assertion_str;
3502 dest+=");\n";
3503 }
3504
3505 dest+='}';
3506
3507 return dest;
3508}
3509
3510std::string
3512{
3513 std::string dest = convert_with_precedence(src.src(), precedence);
3514 dest+='[';
3516 dest+=']';
3517
3518 return dest;
3519}
3520
3521std::string
3523{
3524 std::string dest = convert_with_precedence(src.src(), precedence);
3525 dest+='[';
3527 if(expr_width_opt.has_value())
3528 {
3529 auto upper = plus_exprt{
3530 src.index(),
3531 from_integer(expr_width_opt.value() - 1, src.index().type())};
3532 dest += convert_with_precedence(upper, precedence);
3533 }
3534 else
3535 dest += "?";
3536 dest+=", ";
3538 dest+=']';
3539
3540 return dest;
3541}
3542
3544 const exprt &src,
3545 unsigned &precedence)
3546{
3547 if(src.has_operands())
3548 return convert_norep(src, precedence);
3549
3550 std::string dest="sizeof(";
3551 dest+=convert(static_cast<const typet&>(src.find(ID_type_arg)));
3552 dest+=')';
3553
3554 return dest;
3555}
3556
3558{
3559 std::string dest;
3560 unsigned p;
3561 const auto &cond = src.operands().front();
3562 if(!cond.is_true())
3563 {
3564 dest += convert_with_precedence(cond, p);
3565 dest += ": ";
3566 }
3567
3568 const auto &targets = src.operands()[1];
3569 forall_operands(it, targets)
3570 {
3571 std::string op = convert_with_precedence(*it, p);
3572
3573 if(it != targets.operands().begin())
3574 dest += ", ";
3575
3576 dest += op;
3577 }
3578
3579 return dest;
3580}
3581
3583{
3585 {
3586 const std::size_t width = type_ptr->get_width();
3587 if(width == 8 || width == 16 || width == 32 || width == 64)
3588 {
3589 return convert_function(
3590 src, "__builtin_bitreverse" + std::to_string(width));
3591 }
3592 }
3593
3594 unsigned precedence;
3595 return convert_norep(src, precedence);
3596}
3597
3599{
3600 std::string dest = src.id() == ID_r_ok ? "R_OK"
3601 : src.id() == ID_w_ok ? "W_OK"
3602 : "RW_OK";
3603
3604 dest += '(';
3605
3606 unsigned p;
3607 dest += convert_with_precedence(src.pointer(), p);
3608 dest += ", ";
3609 dest += convert_with_precedence(src.size(), p);
3610
3611 dest += ')';
3612
3613 return dest;
3614}
3615
3616std::string
3618{
3619 // we hide prophecy expressions in C-style output
3620 std::string dest = src.id() == ID_prophecy_r_ok ? "R_OK"
3621 : src.id() == ID_prophecy_w_ok ? "W_OK"
3622 : "RW_OK";
3623
3624 dest += '(';
3625
3626 unsigned p;
3627 dest += convert_with_precedence(src.pointer(), p);
3628 dest += ", ";
3629 dest += convert_with_precedence(src.size(), p);
3630
3631 dest += ')';
3632
3633 return dest;
3634}
3635
3637{
3638 std::string dest = CPROVER_PREFIX "pointer_in_range";
3639
3640 dest += '(';
3641
3642 unsigned p;
3643 dest += convert_with_precedence(src.lower_bound(), p);
3644 dest += ", ";
3645 dest += convert_with_precedence(src.pointer(), p);
3646 dest += ", ";
3647 dest += convert_with_precedence(src.upper_bound(), p);
3648
3649 dest += ')';
3650
3651 return dest;
3652}
3653
3656{
3657 // we hide prophecy expressions in C-style output
3658 std::string dest = CPROVER_PREFIX "pointer_in_range";
3659
3660 dest += '(';
3661
3662 unsigned p;
3663 dest += convert_with_precedence(src.lower_bound(), p);
3664 dest += ", ";
3665 dest += convert_with_precedence(src.pointer(), p);
3666 dest += ", ";
3667 dest += convert_with_precedence(src.upper_bound(), p);
3668
3669 dest += ')';
3670
3671 return dest;
3672}
3673
3675 const exprt &src,
3676 unsigned &precedence)
3677{
3678 precedence=16;
3679
3680 if(src.id()==ID_plus)
3681 return convert_multi_ary(src, "+", precedence=12, false);
3682
3683 else if(src.id()==ID_minus)
3684 return convert_binary(to_binary_expr(src), "-", precedence = 12, true);
3685
3686 else if(src.id()==ID_unary_minus)
3687 return convert_unary(to_unary_expr(src), "-", precedence = 15);
3688
3689 else if(src.id()==ID_unary_plus)
3690 return convert_unary(to_unary_expr(src), "+", precedence = 15);
3691
3692 else if(src.id()==ID_floatbv_typecast)
3693 {
3694 const auto &floatbv_typecast = to_floatbv_typecast_expr(src);
3695
3696 std::string dest="FLOAT_TYPECAST(";
3697
3698 unsigned p0;
3699 std::string tmp0 = convert_with_precedence(floatbv_typecast.op(), p0);
3700
3701 if(p0<=1)
3702 dest+='(';
3703 dest+=tmp0;
3704 if(p0<=1)
3705 dest+=')';
3706
3707 dest+=", ";
3708 dest += convert(src.type());
3709 dest+=", ";
3710
3711 unsigned p1;
3712 std::string tmp1 =
3714
3715 if(p1<=1)
3716 dest+='(';
3717 dest+=tmp1;
3718 if(p1<=1)
3719 dest+=')';
3720
3721 dest+=')';
3722 return dest;
3723 }
3724
3725 else if(src.id()==ID_sign)
3726 {
3727 if(to_unary_expr(src).op().type().id() == ID_floatbv)
3728 return convert_function(src, "signbit");
3729 else
3730 return convert_function(src, "SIGN");
3731 }
3732
3733 else if(src.id()==ID_popcount)
3734 {
3736 return convert_function(src, "__popcnt");
3737 else
3738 return convert_function(src, "__builtin_popcount");
3739 }
3740
3741 else if(src.id()=="pointer_arithmetic")
3742 return convert_pointer_arithmetic(src, precedence=16);
3743
3744 else if(src.id()=="pointer_difference")
3745 return convert_pointer_difference(src, precedence=16);
3746
3747 else if(src.id() == ID_null_object)
3748 return "NULL-object";
3749
3750 else if(src.id()==ID_integer_address ||
3752 src.id()==ID_stack_object ||
3753 src.id()==ID_static_object)
3754 {
3755 return id2string(src.id());
3756 }
3757
3758 else if(src.id()=="builtin-function")
3759 return src.get_string(ID_identifier);
3760
3761 else if(src.id()==ID_array_of)
3762 return convert_array_of(src, precedence=16);
3763
3764 else if(src.id()==ID_bswap)
3765 return convert_function(
3766 src,
3767 "__builtin_bswap" + integer2string(*pointer_offset_bits(
3768 to_unary_expr(src).op().type(), ns)));
3769
3770 else if(src.id().starts_with("byte_extract"))
3772
3773 else if(src.id().starts_with("byte_update"))
3775
3776 else if(src.id()==ID_address_of)
3777 {
3778 const auto &object = to_address_of_expr(src).object();
3779
3780 if(object.id() == ID_label)
3781 return "&&" + object.get_string(ID_identifier);
3782 else if(object.id() == ID_index && to_index_expr(object).index().is_zero())
3783 return convert(to_index_expr(object).array());
3784 else if(to_pointer_type(src.type()).base_type().id() == ID_code)
3785 return convert_unary(to_unary_expr(src), "", precedence = 15);
3786 else
3787 return convert_unary(to_unary_expr(src), "&", precedence = 15);
3788 }
3789
3790 else if(src.id()==ID_dereference)
3791 {
3792 const auto &pointer = to_dereference_expr(src).pointer();
3793
3794 if(src.type().id() == ID_code)
3795 return convert_unary(to_unary_expr(src), "", precedence = 15);
3796 else if(
3797 pointer.id() == ID_plus && pointer.operands().size() == 2 &&
3798 to_plus_expr(pointer).op0().type().id() == ID_pointer)
3799 {
3800 // Note that index[pointer] is legal C, but we avoid it nevertheless.
3801 return convert_index(to_binary_expr(pointer), precedence = 16);
3802 }
3803 else
3804 return convert_unary(to_unary_expr(src), "*", precedence = 15);
3805 }
3806
3807 else if(src.id()==ID_index)
3808 return convert_index(to_binary_expr(src), precedence = 16);
3809
3810 else if(src.id()==ID_member)
3811 return convert_member(to_member_expr(src), precedence=16);
3812
3813 else if(src.id()=="array-member-value")
3814 return convert_array_member_value(src, precedence=16);
3815
3816 else if(src.id()=="struct-member-value")
3818
3819 else if(src.id()==ID_function_application)
3821
3822 else if(src.id()==ID_side_effect)
3823 {
3824 const irep_idt &statement=src.get(ID_statement);
3825 if(statement==ID_preincrement)
3826 return convert_unary(to_unary_expr(src), "++", precedence = 15);
3827 else if(statement==ID_predecrement)
3828 return convert_unary(to_unary_expr(src), "--", precedence = 15);
3829 else if(statement==ID_postincrement)
3830 return convert_unary_post(to_unary_expr(src), "++", precedence = 16);
3831 else if(statement==ID_postdecrement)
3832 return convert_unary_post(to_unary_expr(src), "--", precedence = 16);
3833 else if(statement==ID_assign_plus)
3834 return convert_binary(to_binary_expr(src), "+=", precedence = 2, true);
3835 else if(statement==ID_assign_minus)
3836 return convert_binary(to_binary_expr(src), "-=", precedence = 2, true);
3837 else if(statement==ID_assign_mult)
3838 return convert_binary(to_binary_expr(src), "*=", precedence = 2, true);
3839 else if(statement==ID_assign_div)
3840 return convert_binary(to_binary_expr(src), "/=", precedence = 2, true);
3841 else if(statement==ID_assign_mod)
3842 return convert_binary(to_binary_expr(src), "%=", precedence = 2, true);
3843 else if(statement==ID_assign_shl)
3844 return convert_binary(to_binary_expr(src), "<<=", precedence = 2, true);
3845 else if(statement==ID_assign_shr)
3846 return convert_binary(to_binary_expr(src), ">>=", precedence = 2, true);
3847 else if(statement==ID_assign_bitand)
3848 return convert_binary(to_binary_expr(src), "&=", precedence = 2, true);
3849 else if(statement==ID_assign_bitxor)
3850 return convert_binary(to_binary_expr(src), "^=", precedence = 2, true);
3851 else if(statement==ID_assign_bitor)
3852 return convert_binary(to_binary_expr(src), "|=", precedence = 2, true);
3853 else if(statement==ID_assign)
3854 return convert_binary(to_binary_expr(src), "=", precedence = 2, true);
3855 else if(statement==ID_function_call)
3858 else if(statement == ID_allocate)
3859 return convert_allocate(src, precedence = 15);
3860 else if(statement==ID_printf)
3861 return convert_function(src, "printf");
3862 else if(statement==ID_nondet)
3863 return convert_nondet(src, precedence=16);
3864 else if(statement=="prob_coin")
3865 return convert_prob_coin(src, precedence=16);
3866 else if(statement=="prob_unif")
3867 return convert_prob_uniform(src, precedence=16);
3868 else if(statement==ID_statement_expression)
3870 else if(statement == ID_va_start)
3871 return convert_function(src, CPROVER_PREFIX "va_start");
3872 else
3873 return convert_norep(src, precedence);
3874 }
3875
3876 else if(src.id()==ID_literal)
3877 return convert_literal(src);
3878
3879 else if(src.id()==ID_not)
3880 return convert_unary(to_not_expr(src), "!", precedence = 15);
3881
3882 else if(src.id()==ID_bitnot)
3883 return convert_unary(to_bitnot_expr(src), "~", precedence = 15);
3884
3885 else if(src.id()==ID_mult)
3886 return convert_multi_ary(src, "*", precedence=13, false);
3887
3888 else if(src.id()==ID_div)
3889 return convert_binary(to_div_expr(src), "/", precedence = 13, true);
3890
3891 else if(src.id()==ID_mod)
3892 return convert_binary(to_mod_expr(src), "%", precedence = 13, true);
3893
3894 else if(src.id()==ID_shl)
3895 return convert_binary(to_shl_expr(src), "<<", precedence = 11, true);
3896
3897 else if(src.id()==ID_ashr || src.id()==ID_lshr)
3898 return convert_binary(to_shift_expr(src), ">>", precedence = 11, true);
3899
3900 else if(src.id()==ID_lt || src.id()==ID_gt ||
3901 src.id()==ID_le || src.id()==ID_ge)
3902 {
3903 return convert_binary(
3904 to_binary_relation_expr(src), src.id_string(), precedence = 10, true);
3905 }
3906
3907 else if(src.id()==ID_notequal)
3908 return convert_binary(to_notequal_expr(src), "!=", precedence = 9, true);
3909
3910 else if(src.id()==ID_equal)
3911 return convert_binary(to_equal_expr(src), "==", precedence = 9, true);
3912
3913 else if(src.id()==ID_complex)
3914 return convert_complex(src, precedence=16);
3915
3916 else if(src.id()==ID_bitand)
3917 return convert_multi_ary(src, "&", precedence=8, false);
3918
3919 else if(src.id()==ID_bitxor)
3920 return convert_multi_ary(src, "^", precedence=7, false);
3921
3922 else if(src.id()==ID_bitor)
3923 return convert_multi_ary(src, "|", precedence=6, false);
3924
3925 else if(src.id()==ID_and)
3926 return convert_multi_ary(src, "&&", precedence=5, false);
3927
3928 else if(src.id()==ID_or)
3929 return convert_multi_ary(src, "||", precedence=4, false);
3930
3931 else if(src.id()==ID_xor)
3932 return convert_multi_ary(src, "!=", precedence = 9, false);
3933
3934 else if(src.id()==ID_implies)
3935 return convert_binary(to_implies_expr(src), "==>", precedence = 3, true);
3936
3937 else if(src.id()==ID_if)
3938 return convert_trinary(to_if_expr(src), "?", ":", precedence = 3);
3939
3940 else if(src.id()==ID_forall)
3941 return convert_binding(to_quantifier_expr(src), "forall", precedence = 2);
3942
3943 else if(src.id()==ID_exists)
3944 return convert_binding(to_quantifier_expr(src), "exists", precedence = 2);
3945
3946 else if(src.id()==ID_lambda)
3947 return convert_binding(to_lambda_expr(src), "LAMBDA", precedence = 2);
3948
3949 else if(src.id()==ID_with)
3950 return convert_with(src, precedence=16);
3951
3952 else if(src.id()==ID_update)
3953 return convert_update(to_update_expr(src), precedence = 16);
3954
3955 else if(src.id()==ID_member_designator)
3956 return precedence=16, convert_member_designator(src);
3957
3958 else if(src.id()==ID_index_designator)
3959 return precedence=16, convert_index_designator(src);
3960
3961 else if(src.id()==ID_symbol)
3962 return convert_symbol(src);
3963
3964 else if(src.id()==ID_nondet_symbol)
3966
3967 else if(src.id()==ID_predicate_symbol)
3968 return convert_predicate_symbol(src);
3969
3970 else if(src.id()==ID_predicate_next_symbol)
3972
3973 else if(src.id()==ID_predicate_passive_symbol)
3975
3976 else if(src.id()=="quant_symbol")
3977 return convert_quantified_symbol(src);
3978
3979 else if(src.id()==ID_nondet_bool)
3980 return convert_nondet_bool();
3981
3982 else if(src.id()==ID_object_descriptor)
3984
3985 else if(src.id()=="Hoare")
3986 return convert_Hoare(src);
3987
3988 else if(src.id()==ID_code)
3989 return convert_code(to_code(src));
3990
3991 else if(src.is_constant())
3993
3994 else if(src.id() == ID_annotated_pointer_constant)
3995 {
3998 }
3999
4000 else if(src.id()==ID_string_constant)
4001 return '"' + MetaString(id2string(to_string_constant(src).value())) + '"';
4002
4003 else if(src.id()==ID_struct)
4004 return convert_struct(src, precedence);
4005
4006 else if(src.id()==ID_vector)
4007 return convert_vector(src, precedence);
4008
4009 else if(src.id()==ID_union)
4011
4012 else if(src.id()==ID_array)
4013 return convert_array(src);
4014
4015 else if(src.id() == ID_array_list)
4016 return convert_array_list(src, precedence);
4017
4018 else if(src.id()==ID_typecast)
4020
4021 else if(src.id()==ID_comma)
4022 return convert_comma(src, precedence=1);
4023
4024 else if(src.id()==ID_ptr_object)
4025 return "PTR_OBJECT("+id2string(src.get(ID_identifier))+")";
4026
4027 else if(src.id()==ID_cond)
4028 return convert_cond(src, precedence);
4029
4030 else if(
4033 {
4034 return convert_overflow(src, precedence);
4035 }
4036
4037 else if(src.id()==ID_unknown)
4038 return "*";
4039
4040 else if(src.id()==ID_invalid)
4041 return "#";
4042
4043 else if(src.id()==ID_extractbit)
4045
4046 else if(src.id()==ID_extractbits)
4048
4049 else if(src.id()==ID_initializer_list ||
4050 src.id()==ID_compound_literal)
4051 {
4052 precedence = 15;
4053 return convert_initializer_list(src);
4054 }
4055
4056 else if(src.id()==ID_designated_initializer)
4057 {
4058 precedence = 15;
4060 }
4061
4062 else if(src.id()==ID_sizeof)
4063 return convert_sizeof(src, precedence);
4064
4065 else if(src.id()==ID_let)
4066 return convert_let(to_let_expr(src), precedence=16);
4067
4068 else if(src.id()==ID_type)
4069 return convert(src.type());
4070
4071 else if(src.id() == ID_rol || src.id() == ID_ror)
4072 return convert_rox(to_shift_expr(src), precedence);
4073
4074 else if(src.id() == ID_conditional_target_group)
4075 {
4077 }
4078
4079 else if(src.id() == ID_bitreverse)
4081
4082 else if(src.id() == ID_r_ok || src.id() == ID_w_ok || src.id() == ID_rw_ok)
4084
4085 else if(
4086 auto prophecy_r_or_w_ok =
4088 {
4090 }
4091
4092 else if(src.id() == ID_pointer_in_range)
4094
4095 else if(src.id() == ID_prophecy_pointer_in_range)
4096 {
4099 }
4100
4102 if(function_string_opt.has_value())
4103 return *function_string_opt;
4104
4105 // no C language expression for internal representation
4106 return convert_norep(src, precedence);
4107}
4108
4109std::optional<std::string> expr2ct::convert_function(const exprt &src)
4110{
4111 static const std::map<irep_idt, std::string> function_names = {
4112 {"buffer_size", "BUFFER_SIZE"},
4113 {"is_zero_string", "IS_ZERO_STRING"},
4114 {"object_value", "OBJECT_VALUE"},
4115 {"pointer_base", "POINTER_BASE"},
4116 {"pointer_cons", "POINTER_CONS"},
4117 {"zero_string", "ZERO_STRING"},
4118 {"zero_string_length", "ZERO_STRING_LENGTH"},
4119 {ID_abs, "abs"},
4120 {ID_alignof, "alignof"}, // C uses "_Alignof", C++ uses "alignof"
4121 {ID_builtin_offsetof, "builtin_offsetof"},
4122 {ID_complex_imag, "__imag__"},
4123 {ID_complex_real, "__real__"},
4124 {ID_concatenation, "CONCATENATION"},
4125 {ID_count_leading_zeros, "__builtin_clz"},
4126 {ID_count_trailing_zeros, "__builtin_ctz"},
4127 {ID_dynamic_object, "DYNAMIC_OBJECT"},
4128 {ID_live_object, "LIVE_OBJECT"},
4129 {ID_writeable_object, "WRITEABLE_OBJECT"},
4130 {ID_find_first_set, "__builtin_ffs"},
4131 {ID_separate, "SEPARATE"},
4132 {ID_floatbv_div, "FLOAT/"},
4133 {ID_floatbv_minus, "FLOAT-"},
4134 {ID_floatbv_mult, "FLOAT*"},
4135 {ID_floatbv_plus, "FLOAT+"},
4136 {ID_floatbv_rem, "FLOAT%"},
4137 {ID_gcc_builtin_va_arg, "gcc_builtin_va_arg"},
4138 {ID_get_may, CPROVER_PREFIX "get_may"},
4139 {ID_get_must, CPROVER_PREFIX "get_must"},
4140 {ID_ieee_float_equal, "IEEE_FLOAT_EQUAL"},
4141 {ID_ieee_float_notequal, "IEEE_FLOAT_NOTEQUAL"},
4142 {ID_infinity, "INFINITY"},
4143 {ID_is_dynamic_object, "IS_DYNAMIC_OBJECT"},
4144 {ID_is_invalid_pointer, "IS_INVALID_POINTER"},
4145 {ID_is_invalid_pointer, CPROVER_PREFIX "is_invalid_pointer"},
4146 {ID_isfinite, "isfinite"},
4147 {ID_isinf, "isinf"},
4148 {ID_isnan, "isnan"},
4149 {ID_isnormal, "isnormal"},
4150 {ID_object_size, CPROVER_PREFIX "OBJECT_SIZE"},
4151 {ID_pointer_object, CPROVER_PREFIX "POINTER_OBJECT"},
4152 {ID_pointer_offset, CPROVER_PREFIX "POINTER_OFFSET"},
4153 {ID_loop_entry, CPROVER_PREFIX "loop_entry"},
4154 {ID_saturating_minus, CPROVER_PREFIX "saturating_minus"},
4155 {ID_saturating_plus, CPROVER_PREFIX "saturating_plus"},
4156 {ID_width, "WIDTH"},
4157 };
4158
4159 const auto function_entry = function_names.find(src.id());
4160 if(function_entry == function_names.end())
4161 return {};
4162
4163 return convert_function(src, function_entry->second);
4164}
4165
4166std::string expr2ct::convert(const exprt &src)
4167{
4168 unsigned precedence;
4170}
4171
4178 const typet &src,
4179 const std::string &identifier)
4180{
4181 return convert_rec(src, c_qualifierst(), identifier);
4182}
4183
4184std::string expr2c(
4185 const exprt &expr,
4186 const namespacet &ns,
4187 const expr2c_configurationt &configuration)
4188{
4189 std::string code;
4190 expr2ct expr2c(ns, configuration);
4191 expr2c.get_shorthands(expr);
4192 return expr2c.convert(expr);
4193}
4194
4195std::string expr2c(const exprt &expr, const namespacet &ns)
4196{
4198}
4199
4200std::string type2c(
4201 const typet &type,
4202 const namespacet &ns,
4203 const expr2c_configurationt &configuration)
4204{
4205 expr2ct expr2c(ns, configuration);
4206 // expr2c.get_shorthands(expr);
4207 return expr2c.convert(type);
4208}
4209
4210std::string type2c(const typet &type, const namespacet &ns)
4211{
4213}
4214
4215std::string type2c(
4216 const typet &type,
4217 const std::string &identifier,
4218 const namespacet &ns,
4219 const expr2c_configurationt &configuration)
4220{
4221 expr2ct expr2c(ns, configuration);
4222 return expr2c.convert_with_identifier(type, identifier);
4223}
configt config
Definition config.cpp:25
mp_integer bvrep2integer(const irep_idt &src, std::size_t width, bool is_signed)
convert a bit-vector representation (possibly signed) to integer
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
std::size_t address_bits(const mp_integer &size)
ceil(log2(size))
const shift_exprt & to_shift_expr(const exprt &expr)
Cast an exprt to a shift_exprt.
const shl_exprt & to_shl_expr(const exprt &expr)
Cast an exprt to a shl_exprt.
const extractbits_exprt & to_extractbits_expr(const exprt &expr)
Cast an exprt to an extractbits_exprt.
const bitnot_exprt & to_bitnot_expr(const exprt &expr)
Cast an exprt to a bitnot_exprt.
const bitreverse_exprt & to_bitreverse_expr(const exprt &expr)
Cast an exprt to a bitreverse_exprt.
const extractbit_exprt & to_extractbit_expr(const exprt &expr)
Cast an exprt to an extractbit_exprt.
const bv_typet & to_bv_type(const typet &type)
Cast a typet to a bv_typet.
const fixedbv_typet & to_fixedbv_type(const typet &type)
Cast a typet to a fixedbv_typet.
const bitvector_typet & to_bitvector_type(const typet &type)
Cast a typet to a bitvector_typet.
const floatbv_typet & to_floatbv_type(const typet &type)
Cast a typet to a floatbv_typet.
const unsignedbv_typet & to_unsignedbv_type(const typet &type)
Cast a typet to an unsignedbv_typet.
const signedbv_typet & to_signedbv_type(const typet &type)
Cast a typet to a signedbv_typet.
const byte_update_exprt & to_byte_update_expr(const exprt &expr)
const byte_extract_exprt & to_byte_extract_expr(const exprt &expr)
std::string MetaString(const std::string &in)
Definition c_misc.cpp:95
ANSI-C Misc Utilities.
floatbv_typet float_type()
Definition c_types.cpp:177
unsignedbv_typet unsigned_int_type()
Definition c_types.cpp:36
std::string c_type_as_string(const irep_idt &c_type)
Definition c_types.cpp:251
signedbv_typet signed_int_type()
Definition c_types.cpp:22
bitvector_typet char_type()
Definition c_types.cpp:106
bitvector_typet wchar_t_type()
Definition c_types.cpp:141
floatbv_typet long_double_type()
Definition c_types.cpp:193
floatbv_typet double_type()
Definition c_types.cpp:185
const c_bit_field_typet & to_c_bit_field_type(const typet &type)
Cast a typet to a c_bit_field_typet.
Definition c_types.h:80
const c_enum_typet & to_c_enum_type(const typet &type)
Cast a typet to a c_enum_typet.
Definition c_types.h:335
const c_enum_tag_typet & to_c_enum_tag_type(const typet &type)
Cast a typet to a c_enum_tag_typet.
Definition c_types.h:377
const union_typet & to_union_type(const typet &type)
Cast a typet to a union_typet.
Definition c_types.h:184
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
Definition c_types.h:224
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
Pointer-typed bitvector constant annotated with the pointer expression that the bitvector is the nume...
Arithmetic right shift.
A base class for binary expressions.
Definition std_expr.h:638
exprt & op0()
Definition expr.h:133
exprt & op1()
Definition expr.h:136
A base class for variable bindings (quantifiers, let, lambda)
Definition std_expr.h:3234
exprt & where()
Definition std_expr.h:3265
variablest & variables()
Definition std_expr.h:3255
Bit-wise OR.
Reverse the order of bits in a bit-vector.
std::size_t get_width() const
Definition std_types.h:925
Expression of type type extracted from some object op starting at position offset (given in number of...
Expression corresponding to op() where the bytes starting at position offset (given in number of byte...
C enum tag type, i.e., c_enum_typet with an identifier.
Definition c_types.h:352
The type of C enums.
Definition c_types.h:239
std::vector< c_enum_membert > memberst
Definition c_types.h:275
codet representation of an inline assembler statement.
Definition std_code.h:1253
const irep_idt & get_flavor() const
Definition std_code.h:1263
A codet representing sequential composition of program statements.
Definition std_code.h:130
code_operandst & statements()
Definition std_code.h:138
codet representation of a do while statement.
Definition std_code.h:672
const codet & body() const
Definition std_code.h:689
const exprt & cond() const
Definition std_code.h:679
codet representation of a for statement.
Definition std_code.h:734
const exprt & cond() const
Definition std_code.h:759
const exprt & iter() const
Definition std_code.h:769
const codet & body() const
Definition std_code.h:779
const exprt & init() const
Definition std_code.h:749
A codet representing an assignment in the program.
Definition std_code.h:24
goto_instruction_codet representation of a function call statement.
codet representation of an if-then-else statement.
Definition std_code.h:460
const exprt & cond() const
Definition std_code.h:478
const codet & else_case() const
Definition std_code.h:498
const codet & then_case() const
Definition std_code.h:488
codet representation of a label for branch targets.
Definition std_code.h:959
const irep_idt & get_label() const
Definition std_code.h:967
codet & code()
Definition std_code.h:977
codet representation of a switch-case, i.e. a case statement within a switch.
Definition std_code.h:1023
const exprt & case_op() const
Definition std_code.h:1040
bool is_default() const
Definition std_code.h:1030
Base type of functions.
Definition std_types.h:583
std::vector< parametert > parameterst
Definition std_types.h:586
codet representing a while statement.
Definition std_code.h:610
const exprt & cond() const
Definition std_code.h:617
const codet & body() const
Definition std_code.h:627
Data structure for representing an arbitrary statement in a program.
exprt & op3()
Definition expr.h:142
exprt & op0()
Definition expr.h:133
exprt & op1()
Definition expr.h:136
exprt & op2()
Definition expr.h:139
const irep_idt & get_statement() const
struct configt::ansi_ct ansi_c
A constant literal expression.
Definition std_expr.h:3117
const irep_idt & get_value() const
Definition std_expr.h:3125
bool is_null_pointer() const
Returns true if expr has a pointer type and a value NULL; it also returns true when expr has value ze...
Definition std_expr.cpp:25
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
bool starts_with(const char *s) const
equivalent of as_string().starts_with(s)
Definition dstring.h:95
bool empty() const
Definition dstring.h:89
std::optional< std::string > convert_function(const exprt &src)
Returns a string if src is a function with a known conversion, else returns nullopt.
Definition expr2c.cpp:4109
std::string convert_nondet(const exprt &src, unsigned &precedence)
Definition expr2c.cpp:1182
std::string convert_literal(const exprt &src)
Definition expr2c.cpp:1217
std::string convert_code_continue(unsigned indent)
Definition expr2c.cpp:2836
std::string convert_code_switch_case(const code_switch_caset &src, unsigned indent)
Definition expr2c.cpp:3432
std::string convert_typecast(const typecast_exprt &src, unsigned &precedence)
Definition expr2c.cpp:765
std::string convert_comma(const exprt &src, unsigned precedence)
Definition expr2c.cpp:1254
std::string convert_code_assert(const codet &src, unsigned indent)
Definition expr2c.cpp:3387
std::string convert_union(const exprt &src, unsigned &precedence)
Definition expr2c.cpp:2203
virtual std::string convert_rec(const typet &src, const c_qualifierst &qualifiers, const std::string &declarator)
Definition expr2c.cpp:218
std::string convert_code_expression(const codet &src, unsigned indent)
Definition expr2c.cpp:2978
std::string convert_code_goto(const codet &src, unsigned indent)
Definition expr2c.cpp:2772
std::string convert_code_switch(const codet &src, unsigned indent)
Definition expr2c.cpp:2793
std::string convert_pointer_in_range(const pointer_in_range_exprt &src)
Definition expr2c.cpp:3636
std::string convert_initializer_list(const exprt &src)
Definition expr2c.cpp:2359
std::string convert_quantified_symbol(const exprt &src)
Definition expr2c.cpp:1703
std::string convert_binding(const binding_exprt &, const std::string &symbol, unsigned precedence)
Definition expr2c.cpp:846
std::string convert_function_application(const function_application_exprt &src)
Definition expr2c.cpp:2488
std::string convert_code_unlock(const codet &src, unsigned indent)
Definition expr2c.cpp:3166
std::string convert_code_decl_block(const codet &src, unsigned indent)
Definition expr2c.cpp:2963
static std::string indent_str(unsigned indent)
Definition expr2c.cpp:2576
std::string convert_byte_update(const byte_update_exprt &, unsigned precedence)
Definition expr2c.cpp:1364
std::string convert_code(const codet &src)
Definition expr2c.cpp:3462
std::string convert_pointer_arithmetic(const exprt &src, unsigned &precedence)
Definition expr2c.cpp:1430
std::string convert_let(const let_exprt &, unsigned precedence)
Definition expr2c.cpp:935
std::string convert_nondet_bool()
Definition expr2c.cpp:1709
std::string convert_norep(const exprt &src, unsigned &precedence)
Definition expr2c.cpp:1628
const expr2c_configurationt & configuration
std::unordered_map< irep_idt, std::unordered_set< irep_idt > > ns_collision
std::string convert_code_output(const codet &src, unsigned indent)
Definition expr2c.cpp:3301
std::string convert_code_while(const code_whilet &src, unsigned indent)
Definition expr2c.cpp:2659
std::string convert_index_designator(const exprt &src)
Definition expr2c.cpp:1516
std::string convert_code_frontend_decl(const codet &, unsigned indent)
Definition expr2c.cpp:2846
std::string convert_pointer_difference(const exprt &src, unsigned &precedence)
Definition expr2c.cpp:1467
std::string convert_code_block(const code_blockt &src, unsigned indent)
Definition expr2c.cpp:2940
std::string convert_code_asm(const code_asmt &src, unsigned indent)
Definition expr2c.cpp:2581
std::string convert_prophecy_pointer_in_range(const prophecy_pointer_in_range_exprt &src)
Definition expr2c.cpp:3654
std::string convert_allocate(const exprt &src, unsigned &precedence)
Definition expr2c.cpp:1154
std::string convert_Hoare(const exprt &src)
Definition expr2c.cpp:3467
std::string convert_sizeof(const exprt &src, unsigned &precedence)
Definition expr2c.cpp:3543
std::string convert_code_lock(const codet &src, unsigned indent)
Definition expr2c.cpp:3153
std::string convert_r_or_w_ok(const r_or_w_ok_exprt &src)
Definition expr2c.cpp:3598
std::string convert_code_dowhile(const code_dowhilet &src, unsigned indent)
Definition expr2c.cpp:2685
irep_idt id_shorthand(const irep_idt &identifier) const
Definition expr2c.cpp:75
std::string convert_cond(const exprt &src, unsigned precedence)
Definition expr2c.cpp:1000
std::string convert_side_effect_expr_function_call(const side_effect_expr_function_callt &src)
Definition expr2c.cpp:2516
std::string convert_overflow(const exprt &src, unsigned &precedence)
Definition expr2c.cpp:2545
std::string convert_member(const member_exprt &src, unsigned precedence)
Definition expr2c.cpp:1526
void get_shorthands(const exprt &expr)
Definition expr2c.cpp:116
std::string convert_code_for(const code_fort &src, unsigned indent)
Definition expr2c.cpp:2903
std::string convert_with_identifier(const typet &src, const std::string &identifier)
Build a declaration string, which requires converting both a type and putting an identifier in the sy...
Definition expr2c.cpp:4177
std::string convert_extractbits(const extractbits_exprt &src, unsigned precedence)
Definition expr2c.cpp:3522
virtual std::string convert_struct(const exprt &src, unsigned &precedence)
Definition expr2c.cpp:2067
std::string convert_trinary(const ternary_exprt &src, const std::string &symbol1, const std::string &symbol2, unsigned precedence)
Definition expr2c.cpp:799
std::string convert_prob_coin(const exprt &src, unsigned &precedence)
Definition expr2c.cpp:1207
std::string convert_update(const update_exprt &, unsigned precedence)
Definition expr2c.cpp:962
std::string convert_nondet_symbol(const nondet_symbol_exprt &)
Definition expr2c.cpp:1679
std::string convert_code_printf(const codet &src, unsigned indent)
Definition expr2c.cpp:3227
std::string convert_unary(const unary_exprt &, const std::string &symbol, unsigned precedence)
Definition expr2c.cpp:1134
std::string convert_code_ifthenelse(const code_ifthenelset &src, unsigned indent)
Definition expr2c.cpp:2714
std::string convert_index(const binary_exprt &, unsigned precedence)
Definition expr2c.cpp:1411
std::string convert_member_designator(const exprt &src)
Definition expr2c.cpp:1506
std::string convert_byte_extract(const byte_extract_exprt &, unsigned precedence)
Definition expr2c.cpp:1338
std::string convert_code_label(const code_labelt &src, unsigned indent)
Definition expr2c.cpp:3414
virtual std::string convert_symbol(const exprt &src)
Definition expr2c.cpp:1639
virtual std::string convert_constant(const constant_exprt &src, unsigned &precedence)
Definition expr2c.cpp:1784
std::string convert_code_array_copy(const codet &src, unsigned indent)
Definition expr2c.cpp:3344
std::string convert_statement_expression(const exprt &src, unsigned &precendence)
Definition expr2c.cpp:1192
std::string convert_struct_member_value(const exprt &src, unsigned precedence)
Definition expr2c.cpp:1618
std::string convert_code_dead(const codet &src, unsigned indent)
Definition expr2c.cpp:2889
const namespacet & ns
virtual std::string convert_annotated_pointer_constant(const annotated_pointer_constant_exprt &src, unsigned &precedence)
Definition expr2c.cpp:2046
std::string convert_rox(const shift_exprt &src, unsigned precedence)
Conversion function from rol/ror expressions to C code strings Note that this constructs a complex ex...
Definition expr2c.cpp:2385
virtual std::string convert_with_precedence(const exprt &src, unsigned &precedence)
Definition expr2c.cpp:3674
std::string convert_designated_initializer(const exprt &src)
Definition expr2c.cpp:2445
std::string convert_vector(const exprt &src, unsigned &precedence)
Definition expr2c.cpp:2156
std::string convert_multi_ary(const exprt &src, const std::string &symbol, unsigned precedence, bool full_parentheses)
Definition expr2c.cpp:1086
std::string convert_array_member_value(const exprt &src, unsigned precedence)
Definition expr2c.cpp:1608
std::string convert_unary_post(const exprt &src, const std::string &symbol, unsigned precedence)
Definition expr2c.cpp:1389
std::unordered_map< irep_idt, irep_idt > shorthands
std::string convert_complex(const exprt &src, unsigned precedence)
Definition expr2c.cpp:1278
std::string convert_code_function_call(const code_function_callt &src, unsigned indent)
Definition expr2c.cpp:3179
std::string convert_code_fence(const codet &src, unsigned indent)
Definition expr2c.cpp:3249
std::string convert_bitreverse(const bitreverse_exprt &src)
Definition expr2c.cpp:3582
virtual std::string convert(const typet &src)
Definition expr2c.cpp:213
std::string convert_code_return(const codet &src, unsigned indent)
Definition expr2c.cpp:2751
std::string convert_code_break(unsigned indent)
Definition expr2c.cpp:2784
virtual std::string convert_struct_type(const typet &src, const std::string &qualifiers_str, const std::string &declarator_str)
To generate C-like string for defining the given struct.
Definition expr2c.cpp:650
std::string convert_with(const exprt &src, unsigned precedence)
Definition expr2c.cpp:869
std::string convert_code_frontend_assign(const code_frontend_assignt &, unsigned indent)
Definition expr2c.cpp:3145
std::string convert_object_descriptor(const exprt &src, unsigned &precedence)
Definition expr2c.cpp:1714
std::string convert_predicate_passive_symbol(const exprt &src)
Definition expr2c.cpp:1697
std::string convert_array_list(const exprt &src, unsigned &precedence)
Definition expr2c.cpp:2325
unsigned sizeof_nesting
std::string convert_array_of(const exprt &src, unsigned precedence)
Definition expr2c.cpp:1328
std::string convert_code_array_replace(const codet &src, unsigned indent)
Definition expr2c.cpp:3366
std::string convert_conditional_target_group(const exprt &src)
Definition expr2c.cpp:3557
std::string convert_code_assume(const codet &src, unsigned indent)
Definition expr2c.cpp:3400
virtual std::string convert_array_type(const typet &src, const c_qualifierst &qualifiers, const std::string &declarator_str)
To generate a C-like type declaration of an array.
Definition expr2c.cpp:726
std::string convert_code_input(const codet &src, unsigned indent)
Definition expr2c.cpp:3279
std::string convert_extractbit(const extractbit_exprt &, unsigned precedence)
Definition expr2c.cpp:3511
std::string convert_predicate_next_symbol(const exprt &src)
Definition expr2c.cpp:1691
std::string convert_code_array_set(const codet &src, unsigned indent)
Definition expr2c.cpp:3322
std::string convert_binary(const binary_exprt &, const std::string &symbol, unsigned precedence, bool full_parentheses)
Definition expr2c.cpp:1034
virtual std::string convert_constant_bool(bool boolean_value)
To get the C-like representation of a given boolean value.
Definition expr2c.cpp:2059
std::string convert_predicate_symbol(const exprt &src)
Definition expr2c.cpp:1685
std::string convert_prophecy_r_or_w_ok(const prophecy_r_or_w_ok_exprt &src)
Definition expr2c.cpp:3617
std::string convert_array(const exprt &src)
Definition expr2c.cpp:2222
std::string convert_prob_uniform(const exprt &src, unsigned &precedence)
Definition expr2c.cpp:1222
Base class for all expressions.
Definition expr.h:56
std::vector< exprt > operandst
Definition expr.h:58
bool has_operands() const
Return true if there is at least one operand.
Definition expr.h:91
bool is_true() const
Return whether the expression is a constant representing true.
Definition expr.cpp:27
bool is_constant() const
Return whether the expression is a constant.
Definition expr.h:212
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
Extracts a single bit of a bit-vector operand.
Extracts a sub-range of a bit-vector operand.
std::string to_ansi_c_string() const
Definition fixedbv.h:62
Application of (mathematical) function.
An IEEE 754 floating-point value, including specificiation.
Definition ieee_float.h:117
std::string to_ansi_c_string() const
Definition ieee_float.h:285
There are a large number of kinds of tree structured or tree-like data in CPROVER.
Definition irep.h:364
bool get_bool(const irep_idt &name) const
Definition irep.cpp:57
const irept & find(const irep_idt &name) const
Definition irep.cpp:93
const irep_idt & get(const irep_idt &name) const
Definition irep.cpp:44
void set(const irep_idt &name, const irep_idt &value)
Definition irep.h:412
bool is_not_nil() const
Definition irep.h:372
const std::string & id_string() const
Definition irep.h:391
signed int get_int(const irep_idt &name) const
Definition irep.cpp:62
const irep_idt & id() const
Definition irep.h:388
bool is_nil() const
Definition irep.h:368
const std::string & get_string(const irep_idt &name) const
Definition irep.h:401
A let expression.
Definition std_expr.h:3331
binding_exprt::variablest & variables()
convenience accessor for binding().variables()
Definition std_expr.h:3412
operandst & values()
Definition std_expr.h:3401
exprt & where()
convenience accessor for binding().where()
Definition std_expr.h:3424
Extract member of struct or union.
Definition std_expr.h:2971
const exprt & compound() const
Definition std_expr.h:3020
irep_idt get_component_name() const
Definition std_expr.h:2993
std::size_t get_component_number() const
Definition std_expr.h:3003
Binary minus.
Definition std_expr.h:1061
Modulo defined as lhs-(rhs * truncate(lhs/rhs)).
Definition std_expr.h:1228
Binary multiplication Associativity is not specified.
Definition std_expr.h:1107
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition namespace.h:91
Expression to hold a nondeterministic choice.
Definition std_expr.h:292
const irep_idt & get_identifier() const
Definition std_expr.h:320
The plus expression Associativity is not specified.
Definition std_expr.h:1002
pointer_in_range(a, b, c) evaluates to true iff same_object(a, b, c) ∧ r_ok(a, offset(c)-offset(a)) ∧...
const exprt & upper_bound() const
const exprt & lower_bound() const
const exprt & pointer() const
pointer_in_range (see pointer_in_range_exprt) with prophecy expressions to encode whether a pointer r...
const exprt & upper_bound() const
const exprt & lower_bound() const
const exprt & pointer() const
A base class for a predicate that indicates that an address range is ok to read or write or both.
const exprt & pointer() const
const exprt & size() const
A base class for a predicate that indicates that an address range is ok to read or write or both.
const exprt & size() const
const exprt & pointer() const
A base class for shift and rotate operators.
exprt & distance()
Left shift.
A side_effect_exprt representation of a function call side effect.
Definition std_code.h:1692
exprt::operandst & arguments()
Definition std_code.h:1718
const irep_idt & get_function() const
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
std::vector< componentt > componentst
Definition std_types.h:140
Expression to hold a symbol (variable)
Definition std_expr.h:131
Symbol table entry.
Definition symbol.h:28
bool is_extern
Definition symbol.h:74
bool is_file_local
Definition symbol.h:73
bool is_static_lifetime
Definition symbol.h:70
bool is_parameter
Definition symbol.h:76
source_locationt location
Source code location of definition of symbol.
Definition symbol.h:37
typet type
Type of symbol.
Definition symbol.h:31
bool is_exported
Definition symbol.h:63
irep_idt irep_idt base_name
Name of module the symbol belongs to.
Definition symbol.h:46
An expression with three operands.
Definition std_expr.h:67
exprt & op0()
Definition expr.h:133
exprt & op1()
Definition expr.h:136
exprt & op2()
Definition expr.h:139
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
Generic base class for unary expressions.
Definition std_expr.h:361
const exprt & op() const
Definition std_expr.h:391
A union tag type, i.e., union_typet with an identifier.
Definition c_types.h:199
The union type.
Definition c_types.h:147
Fixed-width bit-vector with unsigned binary interpretation.
Operator to update elements in structs and arrays.
Definition std_expr.h:2782
The vector type.
Definition std_types.h:1064
bool has_prefix(const std::string &s, const std::string &prefix)
Definition converter.cpp:13
#define CPROVER_PREFIX
int isdigit(int c)
Definition ctype.c:24
int isxdigit(int c)
Definition ctype.c:95
static std::unordered_set< irep_idt > find_symbol_identifiers(const goto_programt &src)
Find all identifiers in src.
std::string expr2c(const exprt &expr, const namespacet &ns, const expr2c_configurationt &configuration)
Definition expr2c.cpp:4184
static std::optional< exprt > build_sizeof_expr(const constant_exprt &expr, const namespacet &ns)
Definition expr2c.cpp:1739
std::string type2c(const typet &type, const namespacet &ns, const expr2c_configurationt &configuration)
Definition expr2c.cpp:4200
static std::string clean_identifier(const irep_idt &id)
Definition expr2c.cpp:93
#define forall_operands(it, expr)
Definition expr.h:20
#define forall_expr(it, expr)
Definition expr.h:32
API to expression classes for floating-point arithmetic.
const floatbv_typecast_exprt & to_floatbv_typecast_expr(const exprt &expr)
Cast an exprt to a floatbv_typecast_exprt.
const code_function_callt & to_code_function_call(const goto_instruction_codet &code)
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
static std::string binary(const constant_exprt &src)
std::string from_type(const namespacet &ns, const irep_idt &identifier, const typet &type)
void irep2lisp(const irept &src, lispexprt &dest)
Definition lispirep.cpp:43
literalt pos(literalt a)
Definition literal.h:194
double remainder(double x, double y)
Definition math.c:2069
const quantifier_exprt & to_quantifier_expr(const exprt &expr)
Cast an exprt to a quantifier_exprt.
const function_application_exprt & to_function_application_expr(const exprt &expr)
Cast an exprt to a function_application_exprt.
const lambda_exprt & to_lambda_expr(const exprt &expr)
Cast an exprt to a lambda_exprt.
const mp_integer binary2integer(const std::string &n, bool is_signed)
convert binary string representation to mp_integer
Definition mp_arith.cpp:117
const std::string integer2string(const mp_integer &n, unsigned base)
Definition mp_arith.cpp:103
const std::string integer2binary(const mp_integer &n, std::size_t width)
Definition mp_arith.cpp:64
API to expression classes for Pointers.
const r_or_w_ok_exprt & to_r_or_w_ok_expr(const exprt &expr)
const annotated_pointer_constant_exprt & to_annotated_pointer_constant_expr(const exprt &expr)
Cast an exprt to an annotated_pointer_constant_exprt.
const prophecy_pointer_in_range_exprt & to_prophecy_pointer_in_range_expr(const exprt &expr)
const pointer_in_range_exprt & to_pointer_in_range_expr(const exprt &expr)
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.
std::optional< mp_integer > pointer_offset_bits(const typet &type, const namespacet &ns)
std::optional< exprt > size_of_expr(const typet &type, const namespacet &ns)
Pointer Logic.
#define SYMEX_DYNAMIC_PREFIX
BigInt mp_integer
Definition smt_terms.h:17
#define CHECK_RETURN(CONDITION)
Definition invariant.h:495
#define UNREACHABLE
This should be used to mark dead code.
Definition invariant.h:525
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition invariant.h:534
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
const code_switch_caset & to_code_switch_case(const codet &code)
Definition std_code.h:1077
const code_frontend_returnt & to_code_frontend_return(const codet &code)
Definition std_code.h:943
side_effect_expr_function_callt & to_side_effect_expr_function_call(exprt &expr)
Definition std_code.h:1739
const code_dowhilet & to_code_dowhile(const codet &code)
Definition std_code.h:716
const code_whilet & to_code_while(const codet &code)
Definition std_code.h:654
const code_labelt & to_code_label(const codet &code)
Definition std_code.h:1004
const code_blockt & to_code_block(const codet &code)
Definition std_code.h:203
const code_ifthenelset & to_code_ifthenelse(const codet &code)
Definition std_code.h:530
const code_frontend_assignt & to_code_frontend_assign(const codet &code)
Definition std_code.h:113
code_asmt & to_code_asm(codet &code)
Definition std_code.h:1282
const code_fort & to_code_for(const codet &code)
Definition std_code.h:823
const codet & to_code(const exprt &expr)
auto component(T &struct_expr, const irep_idt &name, const namespacet &ns) -> decltype(struct_expr.op0())
Definition std_expr.cpp:97
const binary_relation_exprt & to_binary_relation_expr(const exprt &expr)
Cast an exprt to a binary_relation_exprt.
Definition std_expr.h:895
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition std_expr.h:1538
const mod_exprt & to_mod_expr(const exprt &expr)
Cast an exprt to a mod_exprt.
Definition std_expr.h:1277
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition std_expr.h:2107
const div_exprt & to_div_expr(const exprt &expr)
Cast an exprt to a div_exprt.
Definition std_expr.h:1206
const binary_exprt & to_binary_expr(const exprt &expr)
Cast an exprt to a binary_exprt.
Definition std_expr.h:715
const plus_exprt & to_plus_expr(const exprt &expr)
Cast an exprt to a plus_exprt.
Definition std_expr.h:1041
const notequal_exprt & to_notequal_expr(const exprt &expr)
Cast an exprt to an notequal_exprt.
Definition std_expr.h:1450
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition std_expr.h:426
const multi_ary_exprt & to_multi_ary_expr(const exprt &expr)
Cast an exprt to a multi_ary_exprt.
Definition std_expr.h:987
const let_exprt & to_let_expr(const exprt &expr)
Cast an exprt to a let_exprt.
Definition std_expr.h:3455
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 union_exprt & to_union_expr(const exprt &expr)
Cast an exprt to a union_exprt.
Definition std_expr.h:1816
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition std_expr.h:3172
const not_exprt & to_not_expr(const exprt &expr)
Cast an exprt to an not_exprt.
Definition std_expr.h:2479
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition std_expr.h:272
const with_exprt & to_with_expr(const exprt &expr)
Cast an exprt to a with_exprt.
Definition std_expr.h:2660
const implies_exprt & to_implies_expr(const exprt &expr)
Cast an exprt to a implies_exprt.
Definition std_expr.h:2250
const update_exprt & to_update_expr(const exprt &expr)
Cast an exprt to an update_exprt.
Definition std_expr.h:2865
const equal_exprt & to_equal_expr(const exprt &expr)
Cast an exprt to an equal_exprt.
Definition std_expr.h:1407
const nondet_symbol_exprt & to_nondet_symbol_expr(const exprt &expr)
Cast an exprt to a nondet_symbol_exprt.
Definition std_expr.h:343
const vector_typet & to_vector_type(const typet &type)
Cast a typet to a vector_typet.
Definition std_types.h:1116
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_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition std_types.h:308
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 complex_typet & to_complex_type(const typet &type)
Cast a typet to a complex_typet.
Definition std_types.h:1158
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 string_constantt & to_string_constant(const exprt &expr)
Stream & join_strings(Stream &&os, const It b, const It e, const Delimiter &delimiter, TransformFunc &&transform_func)
Prints items to an stream, separated by a constant delimiter.
Used for configuring the behaviour of expr2c and type2c.
Definition expr2c.h:21
static expr2c_configurationt clean_configuration
This prints compilable C that loses some of the internal details of the GOTO program.
Definition expr2c.h:52
static expr2c_configurationt default_configuration
This prints a human readable C like syntax that closely mirrors the internals of the GOTO program.
Definition expr2c.h:40
bool has_suffix(const std::string &s, const std::string &suffix)
Definition suffix.h:17
Symbol table entry.
#define size_type
Definition unistd.c:186
bool is_signed(const typet &t)
Convenience function – is the type signed?
Definition util.cpp:45
dstringt irep_idt