CBMC
builtin_functions.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Program Transformation
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
11 
12 #include "goto_convert_class.h"
13 
14 #include <util/arith_tools.h>
15 #include <util/c_types.h>
16 #include <util/cprover_prefix.h>
17 #include <util/expr_initializer.h>
18 #include <util/expr_util.h>
19 #include <util/mathematical_expr.h>
21 #include <util/pointer_expr.h>
22 #include <util/prefix.h>
23 #include <util/rational.h>
24 #include <util/rational_tools.h>
25 #include <util/simplify_expr.h>
26 #include <util/symbol_table.h>
27 
28 #include <langapi/language_util.h>
29 
30 #include "format_strings.h"
31 
33  const exprt &lhs,
34  const symbol_exprt &function,
35  const exprt::operandst &arguments,
36  goto_programt &dest)
37 {
38  const irep_idt &identifier = function.get_identifier();
39 
40  // make it a side effect if there is an LHS
41  if(arguments.size()!=2)
42  {
43  error().source_location=function.find_source_location();
44  error() << "'" << identifier << "' expected to have two arguments" << eom;
45  throw 0;
46  }
47 
48  if(lhs.is_nil())
49  {
50  error().source_location=function.find_source_location();
51  error() << "'" << identifier << "' expected to have LHS" << eom;
52  throw 0;
53  }
54 
55  auto rhs =
56  side_effect_exprt("prob_uniform", lhs.type(), function.source_location());
57 
58  if(lhs.type().id()!=ID_unsignedbv &&
59  lhs.type().id()!=ID_signedbv)
60  {
61  error().source_location=function.find_source_location();
62  error() << "'" << identifier << "' expected other type" << eom;
63  throw 0;
64  }
65 
66  if(arguments[0].type().id()!=lhs.type().id() ||
67  arguments[1].type().id()!=lhs.type().id())
68  {
69  error().source_location=function.find_source_location();
70  error() << "'" << identifier
71  << "' expected operands to be of same type as LHS" << eom;
72  throw 0;
73  }
74 
75  if(!arguments[0].is_constant() ||
76  !arguments[1].is_constant())
77  {
78  error().source_location=function.find_source_location();
79  error() << "'" << identifier
80  << "' expected operands to be constant literals" << eom;
81  throw 0;
82  }
83 
84  mp_integer lb, ub;
85 
86  if(
87  to_integer(to_constant_expr(arguments[0]), lb) ||
88  to_integer(to_constant_expr(arguments[1]), ub))
89  {
90  error().source_location=function.find_source_location();
91  error() << "error converting operands" << eom;
92  throw 0;
93  }
94 
95  if(lb > ub)
96  {
97  error().source_location=function.find_source_location();
98  error() << "expected lower bound to be smaller or equal to the "
99  << "upper bound" << eom;
100  throw 0;
101  }
102 
103  rhs.add_to_operands(exprt{arguments[0]}, exprt{arguments[1]});
104 
105  code_assignt assignment(lhs, rhs);
106  assignment.add_source_location()=function.source_location();
107  copy(assignment, ASSIGN, dest);
108 }
109 
111  const exprt &lhs,
112  const symbol_exprt &function,
113  const exprt::operandst &arguments,
114  goto_programt &dest)
115 {
116  const irep_idt &identifier = function.get_identifier();
117 
118  // make it a side effect if there is an LHS
119  if(arguments.size()!=2)
120  {
121  error().source_location=function.find_source_location();
122  error() << "'" << identifier << "' expected to have two arguments" << eom;
123  throw 0;
124  }
125 
126  if(lhs.is_nil())
127  {
128  error().source_location=function.find_source_location();
129  error() << "'" << identifier << "' expected to have LHS" << eom;
130  throw 0;
131  }
132 
133  side_effect_exprt rhs("prob_coin", lhs.type(), function.source_location());
134 
135  if(lhs.type()!=bool_typet())
136  {
137  error().source_location=function.find_source_location();
138  error() << "'" << identifier << "' expected bool" << eom;
139  throw 0;
140  }
141 
142  if(arguments[0].type().id()!=ID_unsignedbv ||
143  arguments[0].id()!=ID_constant)
144  {
145  error().source_location=function.find_source_location();
146  error() << "'" << identifier << "' expected first operand to be "
147  << "a constant literal of type unsigned long" << eom;
148  throw 0;
149  }
150 
151  if(
152  arguments[1].type().id() != ID_unsignedbv ||
153  arguments[1].id() != ID_constant)
154  {
155  error().source_location = function.find_source_location();
156  error() << "'" << identifier << "' expected second operand to be "
157  << "a constant literal of type unsigned long" << eom;
158  throw 0;
159  }
160 
161  mp_integer num, den;
162 
163  if(
164  to_integer(to_constant_expr(arguments[0]), num) ||
165  to_integer(to_constant_expr(arguments[1]), den))
166  {
167  error().source_location=function.find_source_location();
168  error() << "error converting operands" << eom;
169  throw 0;
170  }
171 
172  if(num-den > mp_integer(0))
173  {
174  error().source_location=function.find_source_location();
175  error() << "probability has to be smaller than 1" << eom;
176  throw 0;
177  }
178 
179  if(den == mp_integer(0))
180  {
181  error().source_location=function.find_source_location();
182  error() << "denominator may not be zero" << eom;
183  throw 0;
184  }
185 
186  rationalt numerator(num), denominator(den);
187  rationalt prob = numerator / denominator;
188 
189  rhs.copy_to_operands(from_rational(prob));
190 
191  code_assignt assignment(lhs, rhs);
192  assignment.add_source_location()=function.source_location();
193  copy(assignment, ASSIGN, dest);
194 }
195 
197  const exprt &lhs,
198  const symbol_exprt &function,
199  const exprt::operandst &arguments,
200  goto_programt &dest)
201 {
202  const irep_idt &f_id = function.get_identifier();
203 
204  PRECONDITION(f_id == CPROVER_PREFIX "printf");
205 
206  codet printf_code(ID_printf, arguments, function.source_location());
207  copy(printf_code, OTHER, dest);
208 }
209 
211  const exprt &lhs,
212  const symbol_exprt &function,
213  const exprt::operandst &arguments,
214  goto_programt &dest)
215 {
216  const irep_idt &f_id = function.get_identifier();
217 
218  if(f_id==CPROVER_PREFIX "scanf")
219  {
220  if(arguments.empty())
221  {
222  error().source_location=function.find_source_location();
223  error() << "scanf takes at least one argument" << eom;
224  throw 0;
225  }
226 
227  irep_idt format_string;
228 
229  if(!get_string_constant(arguments[0], format_string))
230  {
231  // use our model
232  format_token_listt token_list=
233  parse_format_string(id2string(format_string));
234 
235  std::size_t argument_number=1;
236 
237  for(const auto &t : token_list)
238  {
239  const auto type = get_type(t);
240 
241  if(type.has_value())
242  {
243  if(argument_number<arguments.size())
244  {
245  const typecast_exprt ptr(
246  arguments[argument_number], pointer_type(*type));
247  argument_number++;
248 
249  if(type->id() == ID_array)
250  {
251  #if 0
252  // A string. We first need a nondeterministic size.
254  to_array_type(*type).size()=size;
255 
256  const symbolt &tmp_symbol=
258  *type, "scanf_string", dest, function.source_location());
259 
260  const address_of_exprt rhs(
261  index_exprt(
262  tmp_symbol.symbol_expr(),
263  from_integer(0, c_index_type())));
264 
265  // now use array copy
266  codet array_copy_statement;
267  array_copy_statement.set_statement(ID_array_copy);
268  array_copy_statement.operands().resize(2);
269  array_copy_statement.op0()=ptr;
270 \ array_copy_statement.op1()=rhs;
271  array_copy_statement.add_source_location()=
272  function.source_location();
273 
274  copy(array_copy_statement, OTHER, dest);
275  #else
276  const index_exprt new_lhs(
278  const side_effect_expr_nondett rhs(
279  to_array_type(*type).element_type(),
280  function.source_location());
281  code_assignt assign(new_lhs, rhs);
282  assign.add_source_location()=function.source_location();
283  copy(assign, ASSIGN, dest);
284  #endif
285  }
286  else
287  {
288  // make it nondet for now
289  const dereference_exprt new_lhs{ptr};
290  const side_effect_expr_nondett rhs(
291  *type, function.source_location());
292  code_assignt assign(new_lhs, rhs);
293  assign.add_source_location()=function.source_location();
294  copy(assign, ASSIGN, dest);
295  }
296  }
297  }
298  }
299  }
300  else
301  {
302  // we'll just do nothing
303  code_function_callt function_call(lhs, function, arguments);
304  function_call.add_source_location()=function.source_location();
305 
306  copy(function_call, FUNCTION_CALL, dest);
307  }
308  }
309  else
310  UNREACHABLE;
311 }
312 
314  const exprt &function,
315  const exprt::operandst &arguments,
316  goto_programt &dest)
317 {
318  if(arguments.size()<2)
319  {
320  error().source_location=function.find_source_location();
321  error() << "input takes at least two arguments" << eom;
322  throw 0;
323  }
324 
325  copy(code_inputt{arguments, function.source_location()}, OTHER, dest);
326 }
327 
329  const exprt &function,
330  const exprt::operandst &arguments,
331  goto_programt &dest)
332 {
333  if(arguments.size()<2)
334  {
335  error().source_location=function.find_source_location();
336  error() << "output takes at least two arguments" << eom;
337  throw 0;
338  }
339 
340  copy(code_outputt{arguments, function.source_location()}, OTHER, dest);
341 }
342 
344  const exprt &lhs,
345  const symbol_exprt &function,
346  const exprt::operandst &arguments,
347  goto_programt &dest)
348 {
349  if(lhs.is_not_nil())
350  {
352  error() << "atomic_begin does not expect an LHS" << eom;
353  throw 0;
354  }
355 
356  if(!arguments.empty())
357  {
358  error().source_location=function.find_source_location();
359  error() << "atomic_begin takes no arguments" << eom;
360  throw 0;
361  }
362 
363  dest.add(goto_programt::make_atomic_begin(function.source_location()));
364 }
365 
367  const exprt &lhs,
368  const symbol_exprt &function,
369  const exprt::operandst &arguments,
370  goto_programt &dest)
371 {
372  if(lhs.is_not_nil())
373  {
375  error() << "atomic_end does not expect an LHS" << eom;
376  throw 0;
377  }
378 
379  if(!arguments.empty())
380  {
381  error().source_location=function.find_source_location();
382  error() << "atomic_end takes no arguments" << eom;
383  throw 0;
384  }
385 
386  dest.add(goto_programt::make_atomic_end(function.source_location()));
387 }
388 
390  const exprt &lhs,
391  const side_effect_exprt &rhs,
392  goto_programt &dest)
393 {
394  if(lhs.is_nil())
395  {
397  error() << "do_cpp_new without lhs is yet to be implemented" << eom;
398  throw 0;
399  }
400 
401  // build size expression
403  static_cast<const exprt &>(rhs.find(ID_sizeof));
404 
405  bool new_array=rhs.get(ID_statement)==ID_cpp_new_array;
406 
407  exprt count;
408 
409  if(new_array)
410  {
412  static_cast<const exprt &>(rhs.find(ID_size)), object_size.type());
413 
414  // might have side-effect
415  clean_expr(count, dest, ID_cpp);
416  }
417 
418  exprt tmp_symbol_expr;
419 
420  // is this a placement new?
421  if(rhs.operands().empty()) // no, "regular" one
422  {
423  // call __new or __new_array
424  exprt new_symbol=
425  ns.lookup(new_array?"__new_array":"__new").symbol_expr();
426 
427  const code_typet &code_type=
428  to_code_type(new_symbol.type());
429 
430  const typet &return_type=
431  code_type.return_type();
432 
433  assert(code_type.parameters().size()==1 ||
434  code_type.parameters().size()==2);
435 
436  const symbolt &tmp_symbol =
437  new_tmp_symbol(return_type, "new", dest, rhs.source_location(), ID_cpp);
438 
439  tmp_symbol_expr=tmp_symbol.symbol_expr();
440 
441  code_function_callt new_call(new_symbol);
442  if(new_array)
443  new_call.arguments().push_back(count);
444  new_call.arguments().push_back(object_size);
445  new_call.set(
446  ID_C_cxx_alloc_type, to_type_with_subtype(lhs.type()).subtype());
447  new_call.lhs()=tmp_symbol_expr;
448  new_call.add_source_location()=rhs.source_location();
449 
450  convert(new_call, dest, ID_cpp);
451  }
452  else if(rhs.operands().size()==1)
453  {
454  // call __placement_new
455  exprt new_symbol=
456  ns.lookup(
457  new_array?"__placement_new_array":"__placement_new").symbol_expr();
458 
459  const code_typet &code_type=
460  to_code_type(new_symbol.type());
461 
462  const typet &return_type=code_type.return_type();
463 
464  assert(code_type.parameters().size()==2 ||
465  code_type.parameters().size()==3);
466 
467  const symbolt &tmp_symbol =
468  new_tmp_symbol(return_type, "new", dest, rhs.source_location(), ID_cpp);
469 
470  tmp_symbol_expr=tmp_symbol.symbol_expr();
471 
472  code_function_callt new_call(new_symbol);
473  if(new_array)
474  new_call.arguments().push_back(count);
475  new_call.arguments().push_back(object_size);
476  new_call.arguments().push_back(to_unary_expr(rhs).op()); // memory location
477  new_call.set(
478  ID_C_cxx_alloc_type, to_type_with_subtype(lhs.type()).subtype());
479  new_call.lhs()=tmp_symbol_expr;
480  new_call.add_source_location()=rhs.source_location();
481 
482  for(std::size_t i=0; i<code_type.parameters().size(); i++)
483  {
485  new_call.arguments()[i], code_type.parameters()[i].type());
486  }
487 
488  convert(new_call, dest, ID_cpp);
489  }
490  else
491  {
493  error() << "cpp_new expected to have 0 or 1 operands" << eom;
494  throw 0;
495  }
496 
498  lhs,
499  typecast_exprt(tmp_symbol_expr, lhs.type()),
500  rhs.find_source_location()));
501 
502  // grab initializer
503  goto_programt tmp_initializer;
504  cpp_new_initializer(lhs, rhs, tmp_initializer);
505 
506  dest.destructive_append(tmp_initializer);
507 }
508 
511  const exprt &lhs,
512  const side_effect_exprt &rhs,
513  goto_programt &dest)
514 {
515  exprt initializer=
516  static_cast<const exprt &>(rhs.find(ID_initializer));
517 
518  if(initializer.is_not_nil())
519  {
520  if(rhs.get_statement()=="cpp_new[]")
521  {
522  // build loop
523  }
524  else if(rhs.get_statement()==ID_cpp_new)
525  {
526  // just one object
527  const dereference_exprt deref_lhs(
528  lhs, to_pointer_type(rhs.type()).base_type());
529 
530  replace_new_object(deref_lhs, initializer);
531  convert(to_code(initializer), dest, ID_cpp);
532  }
533  else
534  UNREACHABLE;
535  }
536 }
537 
539 {
540  if(src.id()==ID_typecast)
541  return get_array_argument(to_typecast_expr(src).op());
542 
543  if(src.id()!=ID_address_of)
544  {
546  error() << "expected array-pointer as argument" << eom;
547  throw 0;
548  }
549 
550  const auto &address_of_expr = to_address_of_expr(src);
551 
552  if(address_of_expr.object().id() != ID_index)
553  {
555  error() << "expected array-element as argument" << eom;
556  throw 0;
557  }
558 
559  const auto &index_expr = to_index_expr(address_of_expr.object());
560 
561  if(index_expr.array().type().id() != ID_array)
562  {
564  error() << "expected array as argument" << eom;
565  throw 0;
566  }
567 
568  return index_expr.array();
569 }
570 
572  const irep_idt &id,
573  const exprt &lhs,
574  const symbol_exprt &function,
575  const exprt::operandst &arguments,
576  goto_programt &dest)
577 {
578  if(arguments.size()!=2)
579  {
580  error().source_location=function.find_source_location();
581  error() << id << " expects two arguments" << eom;
582  throw 0;
583  }
584 
585  codet array_op_statement(id);
586  array_op_statement.operands()=arguments;
587  array_op_statement.add_source_location()=function.source_location();
588 
589  // lhs is only used with array_equal, in all other cases it should be nil (as
590  // they are of type void)
591  if(id == ID_array_equal)
592  array_op_statement.copy_to_operands(lhs);
593 
594  copy(array_op_statement, OTHER, dest);
595 }
596 
598 {
599  exprt result = skip_typecast(expr);
600 
601  // if it's an address of an lvalue, we take that
602  if(result.id() == ID_address_of)
603  {
604  const auto &address_of_expr = to_address_of_expr(result);
605  if(is_assignable(address_of_expr.object()))
606  result = address_of_expr.object();
607  }
608 
609  while(result.type().id() == ID_array &&
610  to_array_type(result.type()).size().is_one())
611  {
612  result = index_exprt{result, from_integer(0, c_index_type())};
613  }
614 
615  return result;
616 }
617 
619  const exprt &lhs,
620  const symbol_exprt &function,
621  const exprt::operandst &arguments,
622  goto_programt &dest)
623 {
624  PRECONDITION(arguments.size() == 1);
625  const auto enum_expr = arguments.front();
626  const auto enum_type =
627  type_try_dynamic_cast<c_enum_tag_typet>(enum_expr.type());
628  PRECONDITION(enum_type);
629  const c_enum_typet &c_enum_type = ns.follow_tag(*enum_type);
630  const c_enum_typet::memberst enum_values = c_enum_type.members();
631 
632  exprt::operandst disjuncts;
633  for(const auto &enum_value : enum_values)
634  {
635  constant_exprt val{enum_value.get_value(), *enum_type};
636  disjuncts.push_back(equal_exprt(enum_expr, std::move(val)));
637  }
638 
639  code_assignt assignment(lhs, simplify_expr(disjunction(disjuncts), ns));
640  assignment.add_source_location() = function.source_location();
641  assignment.add_source_location().add_pragma("disable:enum-range-check");
642  copy(assignment, ASSIGN, dest);
643 }
644 
646  const exprt &lhs,
647  const symbol_exprt &function,
648  const exprt::operandst &arguments,
649  goto_programt &dest,
650  const irep_idt &mode)
651 {
652  irep_idt identifier = CPROVER_PREFIX "havoc_slice";
653 
654  // We disable checks on the generated instructions
655  // because we add our own rw_ok assertion that takes size into account
656  auto source_location = function.find_source_location();
657  source_location.add_pragma("disable:pointer-check");
658  source_location.add_pragma("disable:pointer-overflow-check");
659  source_location.add_pragma("disable:pointer-primitive-check");
660 
661  // check # arguments
662  if(arguments.size() != 2)
663  {
664  error().source_location = source_location;
665  error() << "'" << identifier << "' expected to have two arguments" << eom;
666  throw 0;
667  }
668 
669  // check argument types
670  if(arguments[0].type().id() != ID_pointer)
671  {
672  error().source_location = source_location;
673  error() << "'" << identifier
674  << "' first argument expected to have `void *` type" << eom;
675  throw 0;
676  }
677 
678  if(arguments[1].type().id() != ID_unsignedbv)
679  {
680  error().source_location = source_location;
681  error() << "'" << identifier
682  << "' second argument expected to have `size_t` type" << eom;
683  throw 0;
684  }
685 
686  // check nil lhs
687  if(lhs.is_not_nil())
688  {
689  error().source_location = source_location;
690  error() << "'" << identifier << "' not expected to have a LHS" << eom;
691  throw 0;
692  }
693 
694  // insert instructions
695  // assert(rw_ok(argument[0], argument[1]));
696  // char nondet_contents[argument[1]];
697  // __CPROVER_array_replace(p, nondet_contents);
698 
699  r_or_w_ok_exprt ok_expr(ID_w_ok, arguments[0], arguments[1]);
700  ok_expr.add_source_location() = source_location;
702  dest.add(goto_programt::make_assertion(ok_expr, source_location));
703  t->source_location_nonconst().set("user-provided", false);
704  t->source_location_nonconst().set_property_class(ID_assertion);
705  t->source_location_nonconst().set_comment(
706  "assertion havoc_slice " + from_expr(ns, identifier, ok_expr));
707 
708  const array_typet array_type(char_type(), simplify_expr(arguments[1], ns));
709 
710  const symbolt &nondet_contents =
711  new_tmp_symbol(array_type, "nondet_contents", dest, source_location, mode);
712  const exprt &nondet_contents_expr = address_of_exprt{index_exprt{
713  nondet_contents.symbol_expr(), from_integer(0, c_index_type())}};
714 
715  const exprt &arg0 =
718  nondet_contents_expr, pointer_type(empty_typet{}));
719 
720  codet array_replace(ID_array_replace, {arg0, arg1}, source_location);
721  dest.add(goto_programt::make_other(array_replace, source_location));
722 }
723 
726  const exprt &lhs,
727  const symbol_exprt &function,
728  const exprt::operandst &arguments,
729  goto_programt &dest,
730  const irep_idt &mode)
731 {
732  if(function.get_bool(ID_C_invalid_object))
733  return; // ignore
734 
735  // lookup symbol
736  const irep_idt &identifier=function.get_identifier();
737 
738  const symbolt *symbol;
739  if(ns.lookup(identifier, symbol))
740  {
741  error().source_location=function.find_source_location();
742  error() << "error: function '" << identifier << "' not found" << eom;
743  throw 0;
744  }
745 
746  if(symbol->type.id()!=ID_code)
747  {
748  error().source_location=function.find_source_location();
749  error() << "error: function '" << identifier
750  << "' type mismatch: expected code" << eom;
751  throw 0;
752  }
753 
754  // User-provided function definitions always take precedence over built-ins.
755  // Front-ends do not (yet) consistently set ID_C_incomplete, thus also test
756  // whether the symbol actually has some non-nil value (which might be
757  // "compiled").
758  if(!symbol->type.get_bool(ID_C_incomplete) && symbol->value.is_not_nil())
759  {
760  do_function_call_symbol(*symbol);
761 
762  code_function_callt function_call(lhs, function, arguments);
763  function_call.add_source_location() = function.source_location();
764 
765  copy(function_call, FUNCTION_CALL, dest);
766 
767  return;
768  }
769 
770  if(identifier == CPROVER_PREFIX "havoc_slice")
771  {
772  do_havoc_slice(lhs, function, arguments, dest, mode);
773  }
774  else if(
775  identifier == CPROVER_PREFIX "assume" || identifier == "__VERIFIER_assume")
776  {
777  if(arguments.size()!=1)
778  {
779  error().source_location=function.find_source_location();
780  error() << "'" << identifier << "' expected to have one argument" << eom;
781  throw 0;
782  }
783 
784  // let's double-check the type of the argument
786  typecast_exprt::conditional_cast(arguments.front(), bool_typet()),
787  function.source_location()));
788 
789  t->source_location_nonconst().set("user-provided", true);
790 
791  if(lhs.is_not_nil())
792  {
793  error().source_location=function.find_source_location();
794  error() << identifier << " expected not to have LHS" << eom;
795  throw 0;
796  }
797  }
798  else if(identifier=="__VERIFIER_error")
799  {
800  if(!arguments.empty())
801  {
802  error().source_location=function.find_source_location();
803  error() << "'" << identifier << "' expected to have no arguments" << eom;
804  throw 0;
805  }
806 
807  goto_programt::targett t = dest.add(
808  goto_programt::make_assertion(false_exprt(), function.source_location()));
809 
810  t->source_location_nonconst().set("user-provided", true);
811  t->source_location_nonconst().set_property_class(ID_assertion);
812 
813  if(lhs.is_not_nil())
814  {
815  error().source_location=function.find_source_location();
816  error() << identifier << " expected not to have LHS" << eom;
817  throw 0;
818  }
819 
820  // __VERIFIER_error has abort() semantics, even if no assertions
821  // are being checked
823  false_exprt(), function.source_location()));
824  a->source_location_nonconst().set("user-provided", true);
825  }
826  else if(
827  identifier == "assert" &&
829  {
830  if(arguments.size()!=1)
831  {
832  error().source_location=function.find_source_location();
833  error() << "'" << identifier << "' expected to have one argument" << eom;
834  throw 0;
835  }
836 
837  // let's double-check the type of the argument
839  typecast_exprt::conditional_cast(arguments.front(), bool_typet()),
840  function.source_location()));
841  t->source_location_nonconst().set("user-provided", true);
842  t->source_location_nonconst().set_property_class(ID_assertion);
843  t->source_location_nonconst().set_comment(
844  "assertion " + from_expr(ns, identifier, arguments.front()));
845 
846  if(lhs.is_not_nil())
847  {
848  error().source_location=function.find_source_location();
849  error() << identifier << " expected not to have LHS" << eom;
850  throw 0;
851  }
852  }
853  else if(identifier == CPROVER_PREFIX "enum_is_in_range")
854  {
855  do_enum_is_in_range(lhs, function, arguments, dest);
856  }
857  else if(
858  identifier == CPROVER_PREFIX "assert" ||
859  identifier == CPROVER_PREFIX "precondition" ||
860  identifier == CPROVER_PREFIX "postcondition")
861  {
862  if(arguments.size()!=2)
863  {
864  error().source_location=function.find_source_location();
865  error() << "'" << identifier << "' expected to have two arguments" << eom;
866  throw 0;
867  }
868 
869  bool is_precondition=
870  identifier==CPROVER_PREFIX "precondition";
871  bool is_postcondition = identifier == CPROVER_PREFIX "postcondition";
872 
873  const irep_idt description=
874  get_string_constant(arguments[1]);
875 
876  // let's double-check the type of the argument
879  function.source_location()));
880 
881  if(is_precondition)
882  {
883  t->source_location_nonconst().set_property_class(ID_precondition);
884  }
885  else if(is_postcondition)
886  {
887  t->source_location_nonconst().set_property_class(ID_postcondition);
888  }
889  else
890  {
891  t->source_location_nonconst().set(
892  "user-provided", !function.source_location().is_built_in());
893  t->source_location_nonconst().set_property_class(ID_assertion);
894  }
895 
896  t->source_location_nonconst().set_comment(description);
897 
898  if(lhs.is_not_nil())
899  {
900  error().source_location=function.find_source_location();
901  error() << identifier << " expected not to have LHS" << eom;
902  throw 0;
903  }
904  }
905  else if(identifier==CPROVER_PREFIX "havoc_object")
906  {
907  if(arguments.size()!=1)
908  {
909  error().source_location=function.find_source_location();
910  error() << "'" << identifier << "' expected to have one argument" << eom;
911  throw 0;
912  }
913 
914  if(lhs.is_not_nil())
915  {
916  error().source_location=function.find_source_location();
917  error() << identifier << " expected not to have LHS" << eom;
918  throw 0;
919  }
920 
921  codet havoc(ID_havoc_object);
922  havoc.add_source_location() = function.source_location();
923  havoc.copy_to_operands(arguments[0]);
924 
925  dest.add(goto_programt::make_other(havoc, function.source_location()));
926  }
927  else if(identifier==CPROVER_PREFIX "printf")
928  {
929  do_printf(lhs, function, arguments, dest);
930  }
931  else if(identifier==CPROVER_PREFIX "scanf")
932  {
933  do_scanf(lhs, function, arguments, dest);
934  }
935  else if(identifier==CPROVER_PREFIX "input" ||
936  identifier=="__CPROVER::input")
937  {
938  if(lhs.is_not_nil())
939  {
940  error().source_location=function.find_source_location();
941  error() << identifier << " expected not to have LHS" << eom;
942  throw 0;
943  }
944 
945  do_input(function, arguments, dest);
946  }
947  else if(identifier==CPROVER_PREFIX "output" ||
948  identifier=="__CPROVER::output")
949  {
950  if(lhs.is_not_nil())
951  {
952  error().source_location=function.find_source_location();
953  error() << identifier << " expected not to have LHS" << eom;
954  throw 0;
955  }
956 
957  do_output(function, arguments, dest);
958  }
959  else if(identifier==CPROVER_PREFIX "atomic_begin" ||
960  identifier=="__CPROVER::atomic_begin" ||
961  identifier=="java::org.cprover.CProver.atomicBegin:()V" ||
962  identifier=="__VERIFIER_atomic_begin")
963  {
964  do_atomic_begin(lhs, function, arguments, dest);
965  }
966  else if(identifier==CPROVER_PREFIX "atomic_end" ||
967  identifier=="__CPROVER::atomic_end" ||
968  identifier=="java::org.cprover.CProver.atomicEnd:()V" ||
969  identifier=="__VERIFIER_atomic_end")
970  {
971  do_atomic_end(lhs, function, arguments, dest);
972  }
973  else if(identifier==CPROVER_PREFIX "prob_biased_coin")
974  {
975  do_prob_coin(lhs, function, arguments, dest);
976  }
977  else if(has_prefix(id2string(identifier), CPROVER_PREFIX "prob_uniform_"))
978  {
979  do_prob_uniform(lhs, function, arguments, dest);
980  }
981  else if(has_prefix(id2string(identifier), "nondet_") ||
982  has_prefix(id2string(identifier), "__VERIFIER_nondet_"))
983  {
984  // make it a side effect if there is an LHS
985  if(lhs.is_nil())
986  return;
987 
988  exprt rhs;
989 
990  // We need to special-case for _Bool, which
991  // can only be 0 or 1.
992  if(lhs.type().id()==ID_c_bool)
993  {
994  rhs = side_effect_expr_nondett(bool_typet(), function.source_location());
995  rhs.set(ID_C_identifier, identifier);
996  rhs=typecast_exprt(rhs, lhs.type());
997  }
998  else
999  {
1000  rhs = side_effect_expr_nondett(lhs.type(), function.source_location());
1001  rhs.set(ID_C_identifier, identifier);
1002  }
1003 
1004  code_assignt assignment(lhs, rhs);
1005  assignment.add_source_location()=function.source_location();
1006  copy(assignment, ASSIGN, dest);
1007  }
1008  else if(has_prefix(id2string(identifier), CPROVER_PREFIX "uninterpreted_"))
1009  {
1010  // make it a side effect if there is an LHS
1011  if(lhs.is_nil())
1012  return;
1013 
1014  if(function.type().get_bool(ID_C_incomplete))
1015  {
1016  error().source_location = function.find_source_location();
1017  error() << "'" << identifier << "' is not declared, "
1018  << "missing type information required to construct call to "
1019  << "uninterpreted function" << eom;
1020  throw 0;
1021  }
1022 
1023  const code_typet &function_call_type = to_code_type(function.type());
1025  for(const auto &parameter : function_call_type.parameters())
1026  domain.push_back(parameter.type());
1027  mathematical_function_typet function_type{domain,
1028  function_call_type.return_type()};
1029  const function_application_exprt rhs(
1030  symbol_exprt{function.get_identifier(), function_type}, arguments);
1031 
1032  code_assignt assignment(lhs, rhs);
1033  assignment.add_source_location()=function.source_location();
1034  copy(assignment, ASSIGN, dest);
1035  }
1036  else if(identifier==CPROVER_PREFIX "array_equal")
1037  {
1038  do_array_op(ID_array_equal, lhs, function, arguments, dest);
1039  }
1040  else if(identifier==CPROVER_PREFIX "array_set")
1041  {
1042  do_array_op(ID_array_set, lhs, function, arguments, dest);
1043  }
1044  else if(identifier==CPROVER_PREFIX "array_copy")
1045  {
1046  do_array_op(ID_array_copy, lhs, function, arguments, dest);
1047  }
1048  else if(identifier==CPROVER_PREFIX "array_replace")
1049  {
1050  do_array_op(ID_array_replace, lhs, function, arguments, dest);
1051  }
1052  else if(identifier=="__assert_fail" ||
1053  identifier=="_assert" ||
1054  identifier=="__assert_c99" ||
1055  identifier=="_wassert")
1056  {
1057  // __assert_fail is Linux
1058  // These take four arguments:
1059  // "expression", "file.c", line, __func__
1060  // klibc has __assert_fail with 3 arguments
1061  // "expression", "file.c", line
1062 
1063  // MingW has
1064  // void _assert (const char*, const char*, int);
1065  // with three arguments:
1066  // "expression", "file.c", line
1067 
1068  // This has been seen in Solaris 11.
1069  // Signature:
1070  // void __assert_c99(
1071  // const char *desc, const char *file, int line, const char *func);
1072 
1073  // _wassert is Windows. The arguments are
1074  // L"expression", L"file.c", line
1075 
1076  if(arguments.size()!=4 &&
1077  arguments.size()!=3)
1078  {
1079  error().source_location=function.find_source_location();
1080  error() << "'" << identifier << "' expected to have four arguments"
1081  << eom;
1082  throw 0;
1083  }
1084 
1085  const irep_idt description=
1086  "assertion "+id2string(get_string_constant(arguments[0]));
1087 
1088  goto_programt::targett t = dest.add(
1089  goto_programt::make_assertion(false_exprt(), function.source_location()));
1090 
1091  t->source_location_nonconst().set("user-provided", true);
1092  t->source_location_nonconst().set_property_class(ID_assertion);
1093  t->source_location_nonconst().set_comment(description);
1094  // we ignore any LHS
1095  }
1096  else if(identifier=="__assert_rtn" ||
1097  identifier=="__assert")
1098  {
1099  // __assert_rtn has been seen on MacOS;
1100  // __assert is FreeBSD and Solaris 11.
1101  // These take four arguments:
1102  // __func__, "file.c", line, "expression"
1103  // On Solaris 11, it's three arguments:
1104  // "expression", "file", line
1105 
1106  irep_idt description;
1107 
1108  if(arguments.size()==4)
1109  {
1110  description=
1111  "assertion "+id2string(get_string_constant(arguments[3]));
1112  }
1113  else if(arguments.size()==3)
1114  {
1115  description=
1116  "assertion "+id2string(get_string_constant(arguments[1]));
1117  }
1118  else
1119  {
1120  error().source_location=function.find_source_location();
1121  error() << "'" << identifier << "' expected to have four arguments"
1122  << eom;
1123  throw 0;
1124  }
1125 
1126  goto_programt::targett t = dest.add(
1127  goto_programt::make_assertion(false_exprt(), function.source_location()));
1128 
1129  t->source_location_nonconst().set("user-provided", true);
1130  t->source_location_nonconst().set_property_class(ID_assertion);
1131  t->source_location_nonconst().set_comment(description);
1132  // we ignore any LHS
1133  }
1134  else if(identifier=="__assert_func")
1135  {
1136  // __assert_func is newlib (used by, e.g., cygwin)
1137  // These take four arguments:
1138  // "file.c", line, __func__, "expression"
1139  if(arguments.size()!=4)
1140  {
1141  error().source_location=function.find_source_location();
1142  error() << "'" << identifier << "' expected to have four arguments"
1143  << eom;
1144  throw 0;
1145  }
1146 
1147  irep_idt description;
1148  try
1149  {
1150  description="assertion "+id2string(get_string_constant(arguments[3]));
1151  }
1152  catch(int)
1153  {
1154  // we might be building newlib, where __assert_func is passed
1155  // a pointer-typed symbol; the warning will still have been
1156  // printed
1157  description="assertion";
1158  }
1159 
1160  goto_programt::targett t = dest.add(
1161  goto_programt::make_assertion(false_exprt(), function.source_location()));
1162 
1163  t->source_location_nonconst().set("user-provided", true);
1164  t->source_location_nonconst().set_property_class(ID_assertion);
1165  t->source_location_nonconst().set_comment(description);
1166  // we ignore any LHS
1167  }
1168  else if(identifier==CPROVER_PREFIX "fence")
1169  {
1170  if(arguments.empty())
1171  {
1172  error().source_location=function.find_source_location();
1173  error() << "'" << identifier << "' expected to have at least one argument"
1174  << eom;
1175  throw 0;
1176  }
1177 
1178  codet fence(ID_fence);
1179 
1180  for(const auto &argument : arguments)
1181  fence.set(get_string_constant(argument), true);
1182 
1183  dest.add(goto_programt::make_other(fence, function.source_location()));
1184  }
1185  else if(identifier=="__builtin_prefetch")
1186  {
1187  // does nothing
1188  }
1189  else if(identifier=="__builtin_unreachable")
1190  {
1191  // says something like UNREACHABLE;
1192  }
1193  else if(identifier==ID_gcc_builtin_va_arg)
1194  {
1195  // This does two things.
1196  // 1) Return value of argument.
1197  // This is just dereferencing.
1198  // 2) Move list pointer to next argument.
1199  // This is just an increment.
1200 
1201  if(arguments.size()!=1)
1202  {
1203  error().source_location=function.find_source_location();
1204  error() << "'" << identifier << "' expected to have one argument" << eom;
1205  throw 0;
1206  }
1207 
1208  exprt list_arg=make_va_list(arguments[0]);
1209 
1210  if(lhs.is_not_nil())
1211  {
1212  exprt list_arg_cast = list_arg;
1213  if(
1214  list_arg.type().id() == ID_pointer &&
1215  to_pointer_type(list_arg.type()).base_type().id() == ID_empty)
1216  {
1217  list_arg_cast =
1219  }
1220 
1221  typet t=pointer_type(lhs.type());
1222  dereference_exprt rhs{
1223  typecast_exprt{dereference_exprt{std::move(list_arg_cast)}, t}};
1224  rhs.add_source_location()=function.source_location();
1225  dest.add(
1226  goto_programt::make_assignment(lhs, rhs, function.source_location()));
1227  }
1228 
1229  code_assignt assign{
1230  list_arg, plus_exprt{list_arg, from_integer(1, pointer_diff_type())}};
1231  assign.rhs().set(
1232  ID_C_va_arg_type, to_code_type(function.type()).return_type());
1234  std::move(assign), function.source_location()));
1235  }
1236  else if(identifier=="__builtin_va_copy")
1237  {
1238  if(arguments.size()!=2)
1239  {
1240  error().source_location=function.find_source_location();
1241  error() << "'" << identifier << "' expected to have two arguments" << eom;
1242  throw 0;
1243  }
1244 
1245  exprt dest_expr=make_va_list(arguments[0]);
1246  const typecast_exprt src_expr(arguments[1], dest_expr.type());
1247 
1248  if(!is_assignable(dest_expr))
1249  {
1251  error() << "va_copy argument expected to be lvalue" << eom;
1252  throw 0;
1253  }
1254 
1256  dest_expr, src_expr, function.source_location()));
1257  }
1258  else if(identifier == "__builtin_va_start" || identifier == "__va_start")
1259  {
1260  // Set the list argument to be the address of the
1261  // parameter argument.
1262  if(arguments.size()!=2)
1263  {
1264  error().source_location=function.find_source_location();
1265  error() << "'" << identifier << "' expected to have two arguments" << eom;
1266  throw 0;
1267  }
1268 
1269  exprt dest_expr=make_va_list(arguments[0]);
1270 
1271  if(!is_assignable(dest_expr))
1272  {
1274  error() << "va_start argument expected to be lvalue" << eom;
1275  throw 0;
1276  }
1277 
1278  if(
1279  dest_expr.type().id() == ID_pointer &&
1280  to_pointer_type(dest_expr.type()).base_type().id() == ID_empty)
1281  {
1282  dest_expr =
1284  }
1285 
1286  side_effect_exprt rhs{
1287  ID_va_start, dest_expr.type(), function.source_location()};
1288  rhs.add_to_operands(
1289  typecast_exprt{address_of_exprt{arguments[1]}, dest_expr.type()});
1290 
1292  std::move(dest_expr), std::move(rhs), function.source_location()));
1293  }
1294  else if(identifier=="__builtin_va_end")
1295  {
1296  // Invalidates the argument. We do so by setting it to NULL.
1297  if(arguments.size()!=1)
1298  {
1299  error().source_location=function.find_source_location();
1300  error() << "'" << identifier << "' expected to have one argument" << eom;
1301  throw 0;
1302  }
1303 
1304  exprt dest_expr=make_va_list(arguments[0]);
1305 
1306  if(!is_assignable(dest_expr))
1307  {
1309  error() << "va_end argument expected to be lvalue" << eom;
1310  throw 0;
1311  }
1312 
1313  // our __builtin_va_list is a pointer
1314  if(dest_expr.type().id() == ID_pointer)
1315  {
1316  const auto zero =
1317  zero_initializer(dest_expr.type(), function.source_location(), ns);
1318  CHECK_RETURN(zero.has_value());
1320  dest_expr, *zero, function.source_location()));
1321  }
1322  }
1323  else if(
1324  identifier == "__builtin_isgreater" ||
1325  identifier == "__builtin_isgreaterequal" ||
1326  identifier == "__builtin_isless" || identifier == "__builtin_islessequal" ||
1327  identifier == "__builtin_islessgreater" ||
1328  identifier == "__builtin_isunordered")
1329  {
1330  // these support two double or two float arguments; we call the
1331  // appropriate internal version
1332  if(arguments.size()!=2 ||
1333  (arguments[0].type()!=double_type() &&
1334  arguments[0].type()!=float_type()) ||
1335  (arguments[1].type()!=double_type() &&
1336  arguments[1].type()!=float_type()))
1337  {
1338  error().source_location=function.find_source_location();
1339  error() << "'" << identifier
1340  << "' expected to have two float/double arguments" << eom;
1341  throw 0;
1342  }
1343 
1344  exprt::operandst new_arguments=arguments;
1345 
1346  bool use_double=arguments[0].type()==double_type();
1347  if(arguments[0].type()!=arguments[1].type())
1348  {
1349  if(use_double)
1350  {
1351  new_arguments[1] =
1352  typecast_exprt(new_arguments[1], arguments[0].type());
1353  }
1354  else
1355  {
1356  new_arguments[0] =
1357  typecast_exprt(new_arguments[0], arguments[1].type());
1358  use_double=true;
1359  }
1360  }
1361 
1362  code_typet f_type=to_code_type(function.type());
1363  f_type.remove_ellipsis();
1364  const typet &a_t=new_arguments[0].type();
1365  f_type.parameters()=
1367 
1368  // replace __builtin_ by CPROVER_PREFIX
1369  std::string name=CPROVER_PREFIX+id2string(identifier).substr(10);
1370  // append d or f for double/float
1371  name+=use_double?'d':'f';
1372 
1373  symbol_exprt new_function=function;
1374  new_function.set_identifier(name);
1375  new_function.type()=f_type;
1376 
1377  code_function_callt function_call(lhs, new_function, new_arguments);
1378  function_call.add_source_location()=function.source_location();
1379 
1380  if(!symbol_table.has_symbol(name))
1381  {
1382  symbolt new_symbol;
1383  new_symbol.base_name=name;
1384  new_symbol.name=name;
1385  new_symbol.type=f_type;
1386  new_symbol.location=function.source_location();
1387  symbol_table.add(new_symbol);
1388  }
1389 
1390  copy(function_call, FUNCTION_CALL, dest);
1391  }
1392  else if(
1393  (identifier == "alloca" || identifier == "__builtin_alloca") &&
1394  function.source_location().get_function() != "alloca")
1395  {
1396  const source_locationt &source_location = function.source_location();
1397  exprt new_lhs = lhs;
1398 
1399  if(lhs.is_nil())
1400  {
1401  new_lhs = new_tmp_symbol(
1402  to_code_type(function.type()).return_type(),
1403  "alloca",
1404  dest,
1405  source_location,
1406  mode)
1407  .symbol_expr();
1408  }
1409 
1410  code_function_callt function_call(new_lhs, function, arguments);
1411  function_call.add_source_location() = source_location;
1412  copy(function_call, FUNCTION_CALL, dest);
1413 
1414  // create a backup copy to ensure that no assignments to the pointer affect
1415  // the destructor code that will execute eventually
1416  if(!lhs.is_nil())
1417  make_temp_symbol(new_lhs, "alloca", dest, mode);
1418 
1419  // mark pointer to alloca result as dead
1420  symbol_exprt dead_object_sym =
1421  ns.lookup(CPROVER_PREFIX "dead_object").symbol_expr();
1422  exprt alloca_result =
1423  typecast_exprt::conditional_cast(new_lhs, dead_object_sym.type());
1424  if_exprt rhs{
1425  side_effect_expr_nondett{bool_typet(), source_location},
1426  std::move(alloca_result),
1427  dead_object_sym};
1428  code_assignt assign{
1429  std::move(dead_object_sym), std::move(rhs), source_location};
1430  targets.destructor_stack.add(assign);
1431  }
1432  else
1433  {
1434  do_function_call_symbol(*symbol);
1435 
1436  // insert function call
1437  code_function_callt function_call(lhs, function, arguments);
1438  function_call.add_source_location()=function.source_location();
1439 
1440  copy(function_call, FUNCTION_CALL, dest);
1441  }
1442 }
exprt::copy_to_operands
void copy_to_operands(const exprt &expr)
Copy the given argument to the end of exprt's operands.
Definition: expr.h:155
goto_programt::make_other
static instructiont make_other(const goto_instruction_codet &_code, const source_locationt &l=source_locationt::nil())
Definition: goto_program.h:948
UNREACHABLE
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:503
goto_convertt::do_havoc_slice
void do_havoc_slice(const exprt &lhs, const symbol_exprt &function, const exprt::operandst &arguments, goto_programt &dest, const irep_idt &mode)
Definition: builtin_functions.cpp:645
symbol_table_baset::has_symbol
bool has_symbol(const irep_idt &name) const
Check whether a symbol exists in the symbol table.
Definition: symbol_table_base.h:87
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:36
typecast_exprt::conditional_cast
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition: std_expr.h:2025
is_assignable
bool is_assignable(const exprt &expr)
Returns true iff the argument is one of the following:
Definition: expr_util.cpp:22
to_unary_expr
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition: std_expr.h:361
goto_convertt::do_cpp_new
virtual void do_cpp_new(const exprt &lhs, const side_effect_exprt &rhs, goto_programt &dest)
Definition: builtin_functions.cpp:389
c_enum_typet
The type of C enums.
Definition: c_types.h:216
skip_typecast
const exprt & skip_typecast(const exprt &expr)
find the expression nested inside typecasts, if any
Definition: expr_util.cpp:217
mp_integer
BigInt mp_integer
Definition: smt_terms.h:17
goto_convertt::do_output
void do_output(const exprt &rhs, const exprt::operandst &arguments, goto_programt &dest)
Definition: builtin_functions.cpp:328
parse_format_string
format_token_listt parse_format_string(const std::string &arg_string)
Definition: format_strings.cpp:186
goto_convertt::ns
namespacet ns
Definition: goto_convert_class.h:52
arith_tools.h
codet::op0
exprt & op0()
Definition: expr.h:125
rational.h
rational_tools.h
goto_convertt::replace_new_object
static void replace_new_object(const exprt &object, exprt &dest)
Definition: goto_convert_side_effect.cpp:409
goto_convertt::convert
void convert(const codet &code, goto_programt &dest, const irep_idt &mode)
converts 'code' and appends the result to 'dest'
Definition: goto_convert.cpp:430
goto_convertt::copy
void copy(const codet &code, goto_program_instruction_typet type, goto_programt &dest)
Definition: goto_convert.cpp:300
CHECK_RETURN
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:495
typet
The type of an expression, extends irept.
Definition: type.h:28
code_typet::parameterst
std::vector< parametert > parameterst
Definition: std_types.h:541
goto_convertt::clean_expr
void clean_expr(exprt &expr, goto_programt &dest, const irep_idt &mode, bool result_is_used=true)
Definition: goto_clean_expr.cpp:166
to_index_expr
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition: std_expr.h:1478
irept::find
const irept & find(const irep_idt &name) const
Definition: irep.cpp:106
goto_convertt::get_array_argument
exprt get_array_argument(const exprt &src)
Definition: builtin_functions.cpp:538
goto_convertt::cpp_new_initializer
void cpp_new_initializer(const exprt &lhs, const side_effect_exprt &rhs, goto_programt &dest)
builds a goto program for object initialization after new
Definition: builtin_functions.cpp:510
symbolt::type
typet type
Type of symbol.
Definition: symbol.h:31
dereference_exprt
Operator to dereference a pointer.
Definition: pointer_expr.h:659
if_exprt
The trinary if-then-else operator.
Definition: std_expr.h:2322
goto_convertt::do_atomic_end
void do_atomic_end(const exprt &lhs, const symbol_exprt &function, const exprt::operandst &arguments, goto_programt &dest)
Definition: builtin_functions.cpp:366
c_enum_typet::memberst
std::vector< c_enum_membert > memberst
Definition: c_types.h:253
prefix.h
goto_convert_class.h
source_locationt::add_pragma
void add_pragma(const irep_idt &pragma)
Definition: source_location.h:184
goto_programt::add
targett add(instructiont &&instruction)
Adds a given instruction at the end.
Definition: goto_program.h:709
to_type_with_subtype
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition: type.h:193
plus_exprt
The plus expression Associativity is not specified.
Definition: std_expr.h:946
format_strings.h
exprt
Base class for all expressions.
Definition: expr.h:55
unary_exprt::op1
const exprt & op1() const =delete
symbolt::base_name
irep_idt base_name
Base (non-scoped) name.
Definition: symbol.h:46
namespace_baset::follow_tag
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
Definition: namespace.cpp:63
to_integer
bool to_integer(const constant_exprt &expr, mp_integer &int_value)
Convert a constant expression expr to an arbitrary-precision integer.
Definition: arith_tools.cpp:20
bool_typet
The Boolean type.
Definition: std_types.h:35
messaget::eom
static eomt eom
Definition: message.h:297
symbol_exprt
Expression to hold a symbol (variable)
Definition: std_expr.h:112
equal_exprt
Equality.
Definition: std_expr.h:1305
code_typet::remove_ellipsis
void remove_ellipsis()
Definition: std_types.h:640
from_rational
constant_exprt from_rational(const rationalt &a)
Definition: rational_tools.cpp:81
code_function_callt::lhs
exprt & lhs()
Definition: goto_instruction_code.h:297
goto_programt::make_assignment
static instructiont make_assignment(const code_assignt &_code, const source_locationt &l=source_locationt::nil())
Create an assignment instruction.
Definition: goto_program.h:1056
zero_initializer
optionalt< exprt > zero_initializer(const typet &type, const source_locationt &source_location, const namespacet &ns)
Create the equivalent of zero for type type.
Definition: expr_initializer.cpp:297
goto_convertt::new_tmp_symbol
symbolt & new_tmp_symbol(const typet &type, const std::string &suffix, goto_programt &dest, const source_locationt &, const irep_idt &mode)
Definition: goto_convert.cpp:1861
irept::get
const irep_idt & get(const irep_idt &name) const
Definition: irep.cpp:45
goto_convertt::do_function_call_symbol
virtual void do_function_call_symbol(const exprt &lhs, const symbol_exprt &function, const exprt::operandst &arguments, goto_programt &dest, const irep_idt &mode)
add function calls to function queue for later processing
Definition: builtin_functions.cpp:725
mathematical_types.h
array_typet::size
const exprt & size() const
Definition: std_types.h:800
code_outputt
A goto_instruction_codet representing the declaration that an output of a particular description has ...
Definition: goto_instruction_code.h:454
goto_convertt::do_enum_is_in_range
void do_enum_is_in_range(const exprt &lhs, const symbol_exprt &function, const exprt::operandst &arguments, goto_programt &dest)
Converts calls to the built in enum_is_in_range function to a test that the given enum value is in th...
Definition: builtin_functions.cpp:618
to_code
const codet & to_code(const exprt &expr)
Definition: std_code_base.h:104
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:84
namespacet::lookup
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Definition: namespace.cpp:138
code_function_callt
goto_instruction_codet representation of a function call statement.
Definition: goto_instruction_code.h:271
irept::is_not_nil
bool is_not_nil() const
Definition: irep.h:380
format_token_listt
std::list< format_tokent > format_token_listt
Definition: format_strings.h:90
to_code_type
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition: std_types.h:744
disjunction
exprt disjunction(const exprt::operandst &op)
1) generates a disjunction for two or more operands 2) for one operand, returns the operand 3) return...
Definition: std_expr.cpp:50
goto_convertt::targets
struct goto_convertt::targetst targets
expr_initializer.h
goto_programt::make_assertion
static instructiont make_assertion(const exprt &g, const source_locationt &l=source_locationt::nil())
Definition: goto_program.h:924
destructor_treet::add
void add(const codet &destructor)
Adds a destructor to the current stack, attaching itself to the current node.
Definition: destructor_tree.cpp:11
messaget::error
mstreamt & error() const
Definition: message.h:399
empty_typet
The empty type.
Definition: std_types.h:50
signed_int_type
signedbv_typet signed_int_type()
Definition: c_types.cpp:40
has_prefix
bool has_prefix(const std::string &s, const std::string &prefix)
Definition: converter.cpp:13
goto_convertt::do_scanf
void do_scanf(const exprt &lhs, const symbol_exprt &function, const exprt::operandst &arguments, goto_programt &dest)
Definition: builtin_functions.cpp:210
id2string
const std::string & id2string(const irep_idt &d)
Definition: irep.h:47
messaget::mstreamt::source_location
source_locationt source_location
Definition: message.h:247
goto_convertt::get_string_constant
irep_idt get_string_constant(const exprt &expr)
Definition: goto_convert.cpp:1821
language_util.h
irept::set
void set(const irep_idt &name, const irep_idt &value)
Definition: irep.h:420
PRECONDITION
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
typet::source_location
const source_locationt & source_location() const
Definition: type.h:90
exprt::find_source_location
const source_locationt & find_source_location() const
Get a source_locationt from the expression or from its operands (non-recursively).
Definition: expr.cpp:165
symbol_exprt::get_identifier
const irep_idt & get_identifier() const
Definition: std_expr.h:142
symbolt::symbol_expr
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
Definition: symbol.cpp:121
float_type
floatbv_typet float_type()
Definition: c_types.cpp:195
pointer_expr.h
function_application_exprt
Application of (mathematical) function.
Definition: mathematical_expr.h:196
mathematical_function_typet::domaint
std::vector< typet > domaint
Definition: mathematical_types.h:63
to_pointer_type
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
Definition: pointer_expr.h:79
simplify_expr
exprt simplify_expr(exprt src, const namespacet &ns)
Definition: simplify_expr.cpp:2931
pointer_type
pointer_typet pointer_type(const typet &subtype)
Definition: c_types.cpp:253
goto_programt::make_atomic_begin
static instructiont make_atomic_begin(const source_locationt &l=source_locationt::nil())
Definition: goto_program.h:970
code_typet
Base type of functions.
Definition: std_types.h:538
OTHER
@ OTHER
Definition: goto_program.h:37
object_size
exprt object_size(const exprt &pointer)
Definition: pointer_predicates.cpp:33
irept::is_nil
bool is_nil() const
Definition: irep.h:376
irept::id
const irep_idt & id() const
Definition: irep.h:396
exprt::operandst
std::vector< exprt > operandst
Definition: expr.h:58
false_exprt
The Boolean constant false.
Definition: std_expr.h:3016
code_typet::parameters
const parameterst & parameters() const
Definition: std_types.h:655
cprover_prefix.h
typet::add_source_location
source_locationt & add_source_location()
Definition: type.h:95
code_function_callt::arguments
argumentst & arguments()
Definition: goto_instruction_code.h:317
double_type
floatbv_typet double_type()
Definition: c_types.cpp:203
side_effect_exprt::get_statement
const irep_idt & get_statement() const
Definition: std_code.h:1472
goto_programt::destructive_append
void destructive_append(goto_programt &p)
Appends the given program p to *this. p is destroyed.
Definition: goto_program.h:692
char_type
bitvector_typet char_type()
Definition: c_types.cpp:124
source_locationt
Definition: source_location.h:18
simplify_expr.h
side_effect_expr_nondett
A side_effect_exprt that returns a non-deterministically chosen value.
Definition: std_code.h:1519
symbol_table_baset::add
bool add(const symbolt &symbol)
Add a new symbol to the symbol table.
Definition: symbol_table_base.cpp:18
expr_util.h
Deprecated expression utility functions.
ASSIGN
@ ASSIGN
Definition: goto_program.h:46
symbolt::value
exprt value
Initial value of symbol.
Definition: symbol.h:34
goto_convertt::do_input
void do_input(const exprt &rhs, const exprt::operandst &arguments, goto_programt &dest)
Definition: builtin_functions.cpp:313
goto_convertt::do_printf
void do_printf(const exprt &lhs, const symbol_exprt &function, const exprt::operandst &arguments, goto_programt &dest)
Definition: builtin_functions.cpp:196
array_typet
Arrays with given size.
Definition: std_types.h:762
goto_convertt::do_atomic_begin
void do_atomic_begin(const exprt &lhs, const symbol_exprt &function, const exprt::operandst &arguments, goto_programt &dest)
Definition: builtin_functions.cpp:343
goto_convertt::targetst::destructor_stack
destructor_treet destructor_stack
Definition: goto_convert_class.h:391
symbolt::location
source_locationt location
Source code location of definition of symbol.
Definition: symbol.h:37
code_inputt
A goto_instruction_codet representing the declaration that an input of a particular description has a...
Definition: goto_instruction_code.h:407
symbolt
Symbol table entry.
Definition: symbol.h:27
from_integer
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
Definition: arith_tools.cpp:100
to_typecast_expr
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition: std_expr.h:2051
pointer_typet::base_type
const typet & base_type() const
The type of the data what we point to.
Definition: pointer_expr.h:35
get_type
optionalt< typet > get_type(const format_tokent &token)
Definition: format_strings.cpp:228
CPROVER_PREFIX
#define CPROVER_PREFIX
Definition: cprover_prefix.h:14
to_array_type
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition: std_types.h:844
code_typet::parametert
Definition: std_types.h:555
FUNCTION_CALL
@ FUNCTION_CALL
Definition: goto_program.h:49
goto_programt
A generic container class for the GOTO intermediate representation of one function.
Definition: goto_program.h:72
goto_convertt::do_array_op
void do_array_op(const irep_idt &id, const exprt &lhs, const symbol_exprt &function, const exprt::operandst &arguments, goto_programt &dest)
Definition: builtin_functions.cpp:571
r_or_w_ok_exprt
A base class for a predicate that indicates that an address range is ok to read or write or both.
Definition: pointer_expr.h:745
type_with_subtypet::subtype
const typet & subtype() const
Definition: type.h:172
goto_convertt::symbol_table
symbol_table_baset & symbol_table
Definition: goto_convert_class.h:51
exprt::is_one
bool is_one() const
Return whether the expression is a constant representing 1.
Definition: expr.cpp:114
code_typet::return_type
const typet & return_type() const
Definition: std_types.h:645
codet::set_statement
void set_statement(const irep_idt &statement)
Definition: std_code_base.h:60
goto_programt::make_assumption
static instructiont make_assumption(const exprt &g, const source_locationt &l=source_locationt::nil())
Definition: goto_program.h:936
to_address_of_expr
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
Definition: pointer_expr.h:408
exprt::operands
operandst & operands()
Definition: expr.h:94
index_exprt
Array index operator.
Definition: std_expr.h:1409
address_of_exprt
Operator to return the address of an object.
Definition: pointer_expr.h:370
exprt::add_source_location
source_locationt & add_source_location()
Definition: expr.h:216
symbol_table.h
Author: Diffblue Ltd.
typecast_exprt
Semantic type conversion.
Definition: std_expr.h:2016
pointer_diff_type
signedbv_typet pointer_diff_type()
Definition: c_types.cpp:238
size_type
unsignedbv_typet size_type()
Definition: c_types.cpp:68
code_assignt
A goto_instruction_codet representing an assignment in the program.
Definition: goto_instruction_code.h:22
constant_exprt
A constant literal expression.
Definition: std_expr.h:2941
c_index_type
bitvector_typet c_index_type()
Definition: c_types.cpp:16
is_constant
bool is_constant(const typet &type)
This method tests, if the given typet is a constant.
Definition: std_types.h:29
constant_exprt::get_value
const irep_idt & get_value() const
Definition: std_expr.h:2950
exprt::source_location
const source_locationt & source_location() const
Definition: expr.h:211
make_va_list
exprt make_va_list(const exprt &expr)
Definition: builtin_functions.cpp:597
mathematical_function_typet
A type for mathematical functions (do not confuse with functions/methods in code)
Definition: mathematical_types.h:58
c_types.h
rationalt
Definition: rational.h:15
from_expr
std::string from_expr(const namespacet &ns, const irep_idt &identifier, const exprt &expr)
Definition: language_util.cpp:38
symbol_exprt::set_identifier
void set_identifier(const irep_idt &identifier)
Definition: std_expr.h:137
symbolt::name
irep_idt name
The unique identifier.
Definition: symbol.h:40
irept::get_bool
bool get_bool(const irep_idt &name) const
Definition: irep.cpp:58
goto_programt::targett
instructionst::iterator targett
Definition: goto_program.h:586
side_effect_exprt
An expression containing a side effect.
Definition: std_code.h:1449
goto_convertt::do_prob_uniform
void do_prob_uniform(const exprt &lhs, const symbol_exprt &function, const exprt::operandst &arguments, goto_programt &dest)
Definition: builtin_functions.cpp:32
c_enum_typet::members
const memberst & members() const
Definition: c_types.h:255
goto_convertt::do_prob_coin
void do_prob_coin(const exprt &lhs, const symbol_exprt &function, const exprt::operandst &arguments, goto_programt &dest)
Definition: builtin_functions.cpp:110
array_typet::element_type
const typet & element_type() const
The type of the elements of the array.
Definition: std_types.h:785
goto_programt::make_atomic_end
static instructiont make_atomic_end(const source_locationt &l=source_locationt::nil())
Definition: goto_program.h:981
mathematical_expr.h
codet
Data structure for representing an arbitrary statement in a program.
Definition: std_code_base.h:28
to_constant_expr
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition: std_expr.h:2992
goto_convertt::make_temp_symbol
void make_temp_symbol(exprt &expr, const std::string &suffix, goto_programt &, const irep_idt &mode)
Definition: goto_convert.cpp:1884