CBMC
goto_convert_side_effect.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/bitvector_expr.h>
16 #include <util/c_types.h>
17 #include <util/expr_util.h>
18 #include <util/fresh_symbol.h>
20 #include <util/std_expr.h>
21 #include <util/symbol.h>
22 
23 #include <ansi-c/c_expr.h>
24 
26  side_effect_exprt &expr,
27  goto_programt &dest,
28  bool result_is_used,
29  bool address_taken,
30  const irep_idt &mode)
31 {
32  const irep_idt statement=expr.get_statement();
33 
34  std::optional<exprt> replacement_expr_opt;
35 
36  if(statement==ID_assign)
37  {
38  auto &old_assignment = to_side_effect_expr_assign(expr);
39  exprt new_lhs = skip_typecast(old_assignment.lhs());
40 
41  if(
42  result_is_used && !address_taken &&
43  assignment_lhs_needs_temporary(old_assignment.lhs()))
44  {
45  if(!old_assignment.rhs().is_constant())
46  make_temp_symbol(old_assignment.rhs(), "assign", dest, mode);
47 
48  replacement_expr_opt =
49  typecast_exprt::conditional_cast(old_assignment.rhs(), new_lhs.type());
50  }
51 
52  exprt new_rhs =
53  typecast_exprt::conditional_cast(old_assignment.rhs(), new_lhs.type());
54  code_assignt new_assignment(std::move(new_lhs), std::move(new_rhs));
55  new_assignment.add_source_location() = expr.source_location();
56 
57  convert_assign(new_assignment, dest, mode);
58  }
59  else if(statement==ID_assign_plus ||
60  statement==ID_assign_minus ||
61  statement==ID_assign_mult ||
62  statement==ID_assign_div ||
63  statement==ID_assign_mod ||
64  statement==ID_assign_shl ||
65  statement==ID_assign_ashr ||
66  statement==ID_assign_lshr ||
67  statement==ID_assign_bitand ||
68  statement==ID_assign_bitxor ||
69  statement==ID_assign_bitor)
70  {
72  expr.operands().size() == 2,
73  id2string(statement) + " expects two arguments",
74  expr.find_source_location());
75 
76  irep_idt new_id;
77 
78  if(statement==ID_assign_plus)
79  new_id=ID_plus;
80  else if(statement==ID_assign_minus)
81  new_id=ID_minus;
82  else if(statement==ID_assign_mult)
83  new_id=ID_mult;
84  else if(statement==ID_assign_div)
85  new_id=ID_div;
86  else if(statement==ID_assign_mod)
87  new_id=ID_mod;
88  else if(statement==ID_assign_shl)
89  new_id=ID_shl;
90  else if(statement==ID_assign_ashr)
91  new_id=ID_ashr;
92  else if(statement==ID_assign_lshr)
93  new_id=ID_lshr;
94  else if(statement==ID_assign_bitand)
95  new_id=ID_bitand;
96  else if(statement==ID_assign_bitxor)
97  new_id=ID_bitxor;
98  else if(statement==ID_assign_bitor)
99  new_id=ID_bitor;
100  else
101  {
102  UNREACHABLE;
103  }
104 
105  const binary_exprt &binary_expr = to_binary_expr(expr);
106  exprt new_lhs = skip_typecast(binary_expr.op0());
107  const typet &op0_type = binary_expr.op0().type();
108 
109  PRECONDITION(
110  op0_type.id() != ID_c_enum_tag && op0_type.id() != ID_c_enum &&
111  op0_type.id() != ID_c_bool && op0_type.id() != ID_bool);
112 
113  exprt rhs = binary_exprt{binary_expr.op0(), new_id, binary_expr.op1()};
114  rhs.add_source_location() = expr.source_location();
115 
116  if(
117  result_is_used && !address_taken &&
118  assignment_lhs_needs_temporary(binary_expr.op0()))
119  {
120  make_temp_symbol(rhs, "assign", dest, mode);
121  replacement_expr_opt =
122  typecast_exprt::conditional_cast(rhs, new_lhs.type());
123  }
124 
125  rhs = typecast_exprt::conditional_cast(rhs, new_lhs.type());
126  rhs.add_source_location() = expr.source_location();
127  code_assignt assignment(new_lhs, rhs);
128  assignment.add_source_location()=expr.source_location();
129 
130  convert(assignment, dest, mode);
131  }
132  else
133  UNREACHABLE;
134 
135  // revert assignment in the expression to its LHS
136  if(replacement_expr_opt.has_value())
137  {
138  exprt new_lhs =
139  typecast_exprt::conditional_cast(*replacement_expr_opt, expr.type());
140  expr.swap(new_lhs);
141  }
142  else if(result_is_used)
143  {
144  exprt lhs = to_binary_expr(expr).op0();
145  // assign_* statements can have an lhs operand with a different type than
146  // that of the overall expression, because of integer promotion (which may
147  // have introduced casts to the lhs).
148  if(expr.type() != lhs.type())
149  {
150  // Skip over those type casts, but also
151  // make sure the resulting expression has the same type as before.
153  lhs.id() == ID_typecast,
154  id2string(expr.id()) +
155  " expression with different operand type expected to have a "
156  "typecast");
158  to_typecast_expr(lhs).op().type() == expr.type(),
159  id2string(expr.id()) + " type mismatch in lhs operand");
160  lhs = to_typecast_expr(lhs).op();
161  }
162  expr.swap(lhs);
163  }
164  else
165  expr.make_nil();
166 }
167 
169  side_effect_exprt &expr,
170  goto_programt &dest,
171  bool result_is_used,
172  bool address_taken,
173  const irep_idt &mode)
174 {
176  expr.operands().size() == 1,
177  "preincrement/predecrement must have one operand",
178  expr.find_source_location());
179 
180  const irep_idt statement=expr.get_statement();
181 
183  statement == ID_preincrement || statement == ID_predecrement,
184  "expects preincrement or predecrement");
185 
186  const auto &op = to_unary_expr(expr).op();
187  const typet &op_type = op.type();
188 
189  PRECONDITION(
190  op_type.id() != ID_c_enum_tag && op_type.id() != ID_c_enum &&
191  op_type.id() != ID_c_bool && op_type.id() != ID_bool);
192 
193  typet constant_type;
194 
195  if(op_type.id() == ID_pointer)
196  constant_type = c_index_type();
197  else if(is_number(op_type))
198  constant_type = op_type;
199  else
200  {
201  UNREACHABLE;
202  }
203 
204  exprt constant;
205 
206  if(constant_type.id() == ID_complex)
207  {
208  exprt real = from_integer(1, to_complex_type(constant_type).subtype());
209  exprt imag = from_integer(0, to_complex_type(constant_type).subtype());
210  constant = complex_exprt(real, imag, to_complex_type(constant_type));
211  }
212  else
213  constant = from_integer(1, constant_type);
214 
215  exprt rhs = binary_exprt{
216  op, statement == ID_preincrement ? ID_plus : ID_minus, std::move(constant)};
217  rhs.add_source_location() = expr.source_location();
218 
219  // Is there a typecast, e.g., for _Bool? If so, transform
220  // t1(op : t2) := op+1 --> op := t2(op+1)
221  exprt lhs;
222  if(op.id() == ID_typecast)
223  {
224  lhs = to_typecast_expr(op).op();
225  rhs = typecast_exprt(rhs, lhs.type());
226  }
227  else
228  {
229  lhs = op;
230  }
231 
232  const bool cannot_use_lhs =
233  result_is_used && !address_taken && assignment_lhs_needs_temporary(lhs);
234  if(cannot_use_lhs)
235  make_temp_symbol(rhs, "pre", dest, mode);
236 
237  code_assignt assignment(lhs, rhs);
238  assignment.add_source_location()=expr.find_source_location();
239 
240  convert(assignment, dest, mode);
241 
242  if(result_is_used)
243  {
244  if(cannot_use_lhs)
245  {
246  auto tmp = typecast_exprt::conditional_cast(rhs, expr.type());
247  expr.swap(tmp);
248  }
249  else
250  {
251  // revert to argument of pre-inc/pre-dec
252  auto tmp = typecast_exprt::conditional_cast(lhs, expr.type());
253  expr.swap(tmp);
254  }
255  }
256  else
257  expr.make_nil();
258 }
259 
261  side_effect_exprt &expr,
262  goto_programt &dest,
263  const irep_idt &mode,
264  bool result_is_used)
265 {
266  goto_programt tmp1, tmp2;
267 
268  // we have ...(op++)...
269 
271  expr.operands().size() == 1,
272  "postincrement/postdecrement must have one operand",
273  expr.find_source_location());
274 
275  const irep_idt statement=expr.get_statement();
276 
278  statement == ID_postincrement || statement == ID_postdecrement,
279  "expects postincrement or postdecrement");
280 
281  const auto &op = to_unary_expr(expr).op();
282  const typet &op_type = op.type();
283 
284  PRECONDITION(
285  op_type.id() != ID_c_enum_tag && op_type.id() != ID_c_enum &&
286  op_type.id() != ID_c_bool && op_type.id() != ID_bool);
287 
288  typet constant_type;
289 
290  if(op_type.id() == ID_pointer)
291  constant_type = c_index_type();
292  else if(is_number(op_type))
293  constant_type = op_type;
294  else
295  {
296  UNREACHABLE;
297  }
298 
299  exprt constant;
300 
301  if(constant_type.id() == ID_complex)
302  {
303  exprt real = from_integer(1, to_complex_type(constant_type).subtype());
304  exprt imag = from_integer(0, to_complex_type(constant_type).subtype());
305  constant = complex_exprt(real, imag, to_complex_type(constant_type));
306  }
307  else
308  constant = from_integer(1, constant_type);
309 
310  binary_exprt rhs{
311  op,
312  statement == ID_postincrement ? ID_plus : ID_minus,
313  std::move(constant)};
314  rhs.add_source_location() = expr.source_location();
315 
316  code_assignt assignment(op, rhs);
317  assignment.add_source_location()=expr.find_source_location();
318 
319  convert(assignment, tmp2, mode);
320 
321  // fix up the expression, if needed
322 
323  if(result_is_used)
324  {
325  exprt tmp = op;
326  std::string suffix = "post";
327  if(auto sym_expr = expr_try_dynamic_cast<symbol_exprt>(tmp))
328  {
329  const irep_idt &base_name = ns.lookup(*sym_expr).base_name;
330  suffix += "_" + id2string(base_name);
331  }
332 
333  make_temp_symbol(tmp, suffix, dest, mode);
334  expr.swap(tmp);
335  }
336  else
337  expr.make_nil();
338 
339  dest.destructive_append(tmp1);
340  dest.destructive_append(tmp2);
341 }
342 
345  goto_programt &dest,
346  const irep_idt &mode,
347  bool result_is_used)
348 {
349  if(!result_is_used)
350  {
351  code_function_callt call(expr.function(), expr.arguments());
352  call.add_source_location()=expr.source_location();
353  convert_function_call(call, dest, mode);
354  expr.make_nil();
355  return;
356  }
357 
358  // get name of function, if available
359  std::string new_base_name = "return_value";
360  irep_idt new_symbol_mode = mode;
361 
362  if(expr.function().id() == ID_symbol)
363  {
364  const irep_idt &identifier =
366  const symbolt &symbol = ns.lookup(identifier);
367 
368  new_base_name+='_';
369  new_base_name+=id2string(symbol.base_name);
370  new_symbol_mode = symbol.mode;
371  }
372 
373  const symbolt &new_symbol = get_fresh_aux_symbol(
374  expr.type(),
376  new_base_name,
377  expr.find_source_location(),
378  new_symbol_mode,
379  symbol_table);
380 
381  {
382  code_frontend_declt decl(new_symbol.symbol_expr());
383  decl.add_source_location()=new_symbol.location;
384  convert_frontend_decl(decl, dest, mode);
385  }
386 
387  {
388  goto_programt tmp_program2;
389  code_function_callt call(
390  new_symbol.symbol_expr(), expr.function(), expr.arguments());
391  call.add_source_location()=new_symbol.location;
392  convert_function_call(call, dest, mode);
393  }
394 
395  static_cast<exprt &>(expr)=new_symbol.symbol_expr();
396 }
397 
399  const exprt &object,
400  exprt &dest)
401 {
402  if(dest.id()=="new_object")
403  dest=object;
404  else
405  Forall_operands(it, dest)
406  replace_new_object(object, *it);
407 }
408 
410  side_effect_exprt &expr,
411  goto_programt &dest,
412  bool result_is_used)
413 {
414  const symbolt &new_symbol = get_fresh_aux_symbol(
415  expr.type(),
417  "new_ptr",
418  expr.find_source_location(),
419  ID_cpp,
420  symbol_table);
421 
422  code_frontend_declt decl(new_symbol.symbol_expr());
423  decl.add_source_location()=new_symbol.location;
424  convert_frontend_decl(decl, dest, ID_cpp);
425 
426  const code_assignt call(new_symbol.symbol_expr(), expr);
427 
428  if(result_is_used)
429  static_cast<exprt &>(expr)=new_symbol.symbol_expr();
430  else
431  expr.make_nil();
432 
433  convert(call, dest, ID_cpp);
434 }
435 
437  side_effect_exprt &expr,
438  goto_programt &dest)
439 {
440  DATA_INVARIANT(expr.operands().size() == 1, "cpp_delete expects one operand");
441 
442  codet tmp(expr.get_statement());
444  tmp.copy_to_operands(to_unary_expr(expr).op());
445  tmp.set(ID_destructor, expr.find(ID_destructor));
446 
447  convert_cpp_delete(tmp, dest);
448 
449  expr.make_nil();
450 }
451 
453  side_effect_exprt &expr,
454  goto_programt &dest,
455  const irep_idt &mode,
456  bool result_is_used)
457 {
458  if(result_is_used)
459  {
460  const symbolt &new_symbol = get_fresh_aux_symbol(
461  expr.type(),
463  "malloc_value",
464  expr.source_location(),
465  mode,
466  symbol_table);
467 
468  code_frontend_declt decl(new_symbol.symbol_expr());
469  decl.add_source_location()=new_symbol.location;
470  convert_frontend_decl(decl, dest, mode);
471 
472  code_assignt call(new_symbol.symbol_expr(), expr);
473  call.add_source_location()=expr.source_location();
474 
475  static_cast<exprt &>(expr)=new_symbol.symbol_expr();
476 
477  convert(call, dest, mode);
478  }
479  else
480  {
481  convert(code_expressiont(std::move(expr)), dest, mode);
482  }
483 }
484 
486  side_effect_exprt &expr,
487  goto_programt &dest)
488 {
489  const irep_idt &mode = expr.get(ID_mode);
491  expr.operands().size() <= 1,
492  "temporary_object takes zero or one operands",
493  expr.find_source_location());
494 
495  symbolt &new_symbol = new_tmp_symbol(
496  expr.type(), "obj", dest, expr.find_source_location(), mode);
497 
498  if(expr.operands().size()==1)
499  {
500  const code_assignt assignment(
501  new_symbol.symbol_expr(), to_unary_expr(expr).op());
502 
503  convert(assignment, dest, mode);
504  }
505 
506  if(expr.find(ID_initializer).is_not_nil())
507  {
509  expr.operands().empty(),
510  "temporary_object takes zero operands",
511  expr.find_source_location());
512  exprt initializer=static_cast<const exprt &>(expr.find(ID_initializer));
513  replace_new_object(new_symbol.symbol_expr(), initializer);
514 
515  convert(to_code(initializer), dest, mode);
516  }
517 
518  static_cast<exprt &>(expr)=new_symbol.symbol_expr();
519 }
520 
522  side_effect_exprt &expr,
523  goto_programt &dest,
524  const irep_idt &mode,
525  bool result_is_used)
526 {
527  // This is a gcc extension of the form ({ ....; expr; })
528  // The value is that of the final expression.
529  // The expression is copied into a temporary before the
530  // scope is destroyed.
531 
533 
534  if(!result_is_used)
535  {
536  convert(code, dest, mode);
537  expr.make_nil();
538  return;
539  }
540 
542  code.get_statement() == ID_block,
543  "statement_expression takes block as operand",
544  code.find_source_location());
545 
547  !code.operands().empty(),
548  "statement_expression takes non-empty block as operand",
549  expr.find_source_location());
550 
551  // get last statement from block, following labels
553 
554  source_locationt source_location=last.find_source_location();
555 
556  symbolt &new_symbol = new_tmp_symbol(
557  expr.type(), "statement_expression", dest, source_location, mode);
558 
559  symbol_exprt tmp_symbol_expr(new_symbol.name, new_symbol.type);
560  tmp_symbol_expr.add_source_location()=source_location;
561 
562  if(last.get(ID_statement)==ID_expression)
563  {
564  // we turn this into an assignment
566  last=code_assignt(tmp_symbol_expr, e);
567  last.add_source_location()=source_location;
568  }
569  else if(last.get(ID_statement)==ID_assign)
570  {
571  exprt e=to_code_assign(last).lhs();
572  code_assignt assignment(tmp_symbol_expr, e);
573  assignment.add_source_location()=source_location;
574  code.operands().push_back(assignment);
575  }
576  else
577  {
578  UNREACHABLE;
579  }
580 
581  {
582  goto_programt tmp;
583  convert(code, tmp, mode);
584  dest.destructive_append(tmp);
585  }
586 
587  static_cast<exprt &>(expr)=tmp_symbol_expr;
588 }
589 
592  goto_programt &dest,
593  bool result_is_used,
594  const irep_idt &mode)
595 {
596  const irep_idt &statement = expr.get_statement();
597  const exprt &lhs = expr.lhs();
598  const exprt &rhs = expr.rhs();
599  const exprt &result = expr.result();
600 
601  if(result.type().id() != ID_pointer)
602  {
603  // result of the arithmetic operation is _not_ used, just evaluate side
604  // effects
605  exprt tmp = result;
606  clean_expr(tmp, dest, mode, false);
607 
608  // the is-there-an-overflow result may be used
609  if(result_is_used)
610  {
611  binary_overflow_exprt overflow_check{
613  statement,
615  overflow_check.add_source_location() = expr.source_location();
616  expr.swap(overflow_check);
617  }
618  else
619  expr.make_nil();
620  }
621  else
622  {
623  const typet &arith_type = to_pointer_type(result.type()).base_type();
624  irep_idt arithmetic_operation =
625  statement == ID_overflow_plus
626  ? ID_plus
627  : statement == ID_overflow_minus
628  ? ID_minus
629  : statement == ID_overflow_mult ? ID_mult : ID_nil;
630  CHECK_RETURN(arithmetic_operation != ID_nil);
631  exprt overflow_with_result = overflow_result_exprt{
632  typecast_exprt::conditional_cast(lhs, arith_type),
633  arithmetic_operation,
634  typecast_exprt::conditional_cast(rhs, arith_type)};
635  overflow_with_result.add_source_location() = expr.source_location();
636 
637  if(result_is_used)
638  make_temp_symbol(overflow_with_result, "overflow_result", dest, mode);
639 
640  const struct_typet::componentst &result_comps =
641  to_struct_type(overflow_with_result.type()).components();
642  CHECK_RETURN(result_comps.size() == 2);
643  code_assignt result_assignment{
646  member_exprt{overflow_with_result, result_comps[0]}, arith_type),
647  expr.source_location()};
648  convert_assign(result_assignment, dest, mode);
649 
650  if(result_is_used)
651  {
652  member_exprt overflow_check{overflow_with_result, result_comps[1]};
653  overflow_check.add_source_location() = expr.source_location();
654 
655  expr.swap(overflow_check);
656  }
657  else
658  expr.make_nil();
659  }
660 }
661 
663  side_effect_exprt &expr,
664  goto_programt &dest,
665  const irep_idt &mode,
666  bool result_is_used,
667  bool address_taken)
668 {
669  const irep_idt &statement=expr.get_statement();
670 
671  if(statement==ID_function_call)
673  to_side_effect_expr_function_call(expr), dest, mode, result_is_used);
674  else if(statement==ID_assign ||
675  statement==ID_assign_plus ||
676  statement==ID_assign_minus ||
677  statement==ID_assign_mult ||
678  statement==ID_assign_div ||
679  statement==ID_assign_bitor ||
680  statement==ID_assign_bitxor ||
681  statement==ID_assign_bitand ||
682  statement==ID_assign_lshr ||
683  statement==ID_assign_ashr ||
684  statement==ID_assign_shl ||
685  statement==ID_assign_mod)
686  remove_assignment(expr, dest, result_is_used, address_taken, mode);
687  else if(statement==ID_postincrement ||
688  statement==ID_postdecrement)
689  remove_post(expr, dest, mode, result_is_used);
690  else if(statement==ID_preincrement ||
691  statement==ID_predecrement)
692  remove_pre(expr, dest, result_is_used, address_taken, mode);
693  else if(statement==ID_cpp_new ||
694  statement==ID_cpp_new_array)
695  remove_cpp_new(expr, dest, result_is_used);
696  else if(statement==ID_cpp_delete ||
697  statement==ID_cpp_delete_array)
698  remove_cpp_delete(expr, dest);
699  else if(statement==ID_allocate)
700  remove_malloc(expr, dest, mode, result_is_used);
701  else if(statement==ID_temporary_object)
702  remove_temporary_object(expr, dest);
703  else if(statement==ID_statement_expression)
704  remove_statement_expression(expr, dest, mode, result_is_used);
705  else if(statement==ID_nondet)
706  {
707  // these are fine
708  }
709  else if(statement==ID_skip)
710  {
711  expr.make_nil();
712  }
713  else if(statement==ID_throw)
714  {
716  expr.find(ID_exception_list), expr.type(), expr.source_location()));
717  code.op0().operands().swap(expr.operands());
718  code.add_source_location() = expr.source_location();
720  std::move(code), expr.source_location(), THROW, nil_exprt(), {}));
721 
722  // the result can't be used, these are void
723  expr.make_nil();
724  }
725  else if(
726  statement == ID_overflow_plus || statement == ID_overflow_minus ||
727  statement == ID_overflow_mult)
728  {
730  to_side_effect_expr_overflow(expr), dest, result_is_used, mode);
731  }
732  else
733  {
734  UNREACHABLE;
735  }
736 }
std::unordered_set< symbol_exprt, irep_hash > address_taken(const std::vector< exprt > &src)
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
API to expression classes for bitvectors.
API to expression classes that are internal to the C frontend.
const side_effect_expr_overflowt & to_side_effect_expr_overflow(const exprt &expr)
Cast an exprt to a side_effect_expr_overflowt.
Definition: c_expr.h:182
bitvector_typet c_index_type()
Definition: c_types.cpp:16
A base class for binary expressions.
Definition: std_expr.h:638
exprt & op1()
Definition: expr.h:136
exprt & op0()
Definition: expr.h:133
A Boolean expression returning true, iff operation kind would result in an overflow when applied to o...
A goto_instruction_codet representing an assignment in the program.
codet & find_last_statement()
Definition: std_code.cpp:96
codet representation of an expression statement.
Definition: std_code.h:1394
const exprt & expression() const
Definition: std_code.h:1401
A codet representing the declaration of a local variable.
Definition: std_code.h:347
goto_instruction_codet representation of a function call statement.
Data structure for representing an arbitrary statement in a program.
Definition: std_code_base.h:29
exprt & op0()
Definition: expr.h:133
const irep_idt & get_statement() const
Definition: std_code_base.h:65
Complex constructor from a pair of numbers.
Definition: std_expr.h:1911
Operator to dereference a pointer.
Definition: pointer_expr.h:834
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:38
Base class for all expressions.
Definition: expr.h:56
const source_locationt & find_source_location() const
Get a source_locationt from the expression or from its operands (non-recursively).
Definition: expr.cpp:147
void copy_to_operands(const exprt &expr)
Copy the given argument to the end of exprt's operands.
Definition: expr.h:163
source_locationt & add_source_location()
Definition: expr.h:236
const source_locationt & source_location() const
Definition: expr.h:231
typet & type()
Return the type of the expression.
Definition: expr.h:84
operandst & operands()
Definition: expr.h:94
void remove_temporary_object(side_effect_exprt &expr, goto_programt &dest)
void remove_function_call(side_effect_expr_function_callt &expr, goto_programt &dest, const irep_idt &mode, bool result_is_used)
symbol_table_baset & symbol_table
void remove_pre(side_effect_exprt &expr, goto_programt &dest, bool result_is_used, bool address_taken, const irep_idt &mode)
void convert_assign(const code_assignt &code, goto_programt &dest, const irep_idt &mode)
void remove_overflow(side_effect_expr_overflowt &expr, goto_programt &dest, bool result_is_used, const irep_idt &mode)
void remove_post(side_effect_exprt &expr, goto_programt &dest, const irep_idt &mode, bool result_is_used)
void remove_malloc(side_effect_exprt &expr, goto_programt &dest, const irep_idt &mode, bool result_is_used)
void remove_cpp_delete(side_effect_exprt &expr, goto_programt &dest)
std::string tmp_symbol_prefix
void convert_frontend_decl(const code_frontend_declt &, goto_programt &, const irep_idt &mode)
void remove_side_effect(side_effect_exprt &expr, goto_programt &dest, const irep_idt &mode, bool result_is_used, bool address_taken)
void convert_function_call(const code_function_callt &code, goto_programt &dest, const irep_idt &mode)
symbolt & new_tmp_symbol(const typet &type, const std::string &suffix, goto_programt &dest, const source_locationt &, const irep_idt &mode)
void remove_statement_expression(side_effect_exprt &expr, goto_programt &dest, const irep_idt &mode, bool result_is_used)
void convert_cpp_delete(const codet &code, goto_programt &dest)
void clean_expr(exprt &expr, goto_programt &dest, const irep_idt &mode, bool result_is_used=true)
void remove_assignment(side_effect_exprt &expr, goto_programt &dest, bool result_is_used, bool address_taken, const irep_idt &mode)
void convert(const codet &code, goto_programt &dest, const irep_idt &mode)
converts 'code' and appends the result to 'dest'
void remove_cpp_new(side_effect_exprt &expr, goto_programt &dest, bool result_is_used)
static void replace_new_object(const exprt &object, exprt &dest)
void make_temp_symbol(exprt &expr, const std::string &suffix, goto_programt &, const irep_idt &mode)
static bool assignment_lhs_needs_temporary(const exprt &lhs)
This class represents an instruction in the GOTO intermediate representation.
Definition: goto_program.h:181
A generic container class for the GOTO intermediate representation of one function.
Definition: goto_program.h:73
void destructive_append(goto_programt &p)
Appends the given program p to *this. p is destroyed.
Definition: goto_program.h:722
targett add(instructiont &&instruction)
Adds a given instruction at the end.
Definition: goto_program.h:739
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:408
bool is_not_nil() const
Definition: irep.h:368
const irep_idt & id() const
Definition: irep.h:384
void make_nil()
Definition: irep.h:442
void swap(irept &irep)
Definition: irep.h:430
Extract member of struct or union.
Definition: std_expr.h:2841
mstreamt & result() const
Definition: message.h:409
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Definition: namespace.cpp:148
The NIL expression.
Definition: std_expr.h:3073
An expression returning both the result of the arithmetic operation under wrap-around semantics as we...
const typet & base_type() const
The type of the data what we point to.
Definition: pointer_expr.h:35
A side_effect_exprt representation of a function call side effect.
Definition: std_code.h:1692
exprt::operandst & arguments()
Definition: std_code.h:1718
A Boolean expression returning true, iff the result of performing operation kind on operands a and b ...
Definition: c_expr.h:117
A side_effect_exprt representation of a side effect that throws an exception.
Definition: std_code.h:1757
An expression containing a side effect.
Definition: std_code.h:1450
const irep_idt & get_statement() const
Definition: std_code.h:1472
const componentst & components() const
Definition: std_types.h:147
std::vector< componentt > componentst
Definition: std_types.h:140
Expression to hold a symbol (variable)
Definition: std_expr.h:131
const irep_idt & get_identifier() const
Definition: std_expr.h:160
Symbol table entry.
Definition: symbol.h:28
irep_idt base_name
Base (non-scoped) name.
Definition: symbol.h:46
source_locationt location
Source code location of definition of symbol.
Definition: symbol.h:37
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
Definition: symbol.cpp:121
typet type
Type of symbol.
Definition: symbol.h:31
irep_idt name
The unique identifier.
Definition: symbol.h:40
irep_idt mode
Language mode.
Definition: symbol.h:49
Semantic type conversion.
Definition: std_expr.h:2068
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition: std_expr.h:2076
The type of an expression, extends irept.
Definition: type.h:29
const exprt & op() const
Definition: std_expr.h:391
#define Forall_operands(it, expr)
Definition: expr.h:27
const exprt & skip_typecast(const exprt &expr)
find the expression nested inside typecasts, if any
Definition: expr_util.cpp:219
Deprecated expression utility functions.
symbolt & get_fresh_aux_symbol(const typet &type, const std::string &name_prefix, const std::string &basename_prefix, const source_locationt &source_location, const irep_idt &symbol_mode, const namespacet &ns, symbol_table_baset &symbol_table)
Installs a fresh-named symbol with respect to the given namespace ns with the requested name pattern ...
Fresh auxiliary symbol creation.
Program Transformation.
const code_assignt & to_code_assign(const goto_instruction_codet &code)
@ THROW
Definition: goto_program.h:50
const std::string & id2string(const irep_idt &d)
Definition: irep.h:40
bool is_number(const typet &type)
Returns true if the type is a rational, real, integer, natural, complex, unsignedbv,...
Mathematical types.
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
Definition: pointer_expr.h:93
#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 PRECONDITION(CONDITION)
Definition: invariant.h:463
#define INVARIANT_WITH_DIAGNOSTICS(CONDITION, REASON,...)
Same as invariant, with one or more diagnostics attached Diagnostics can be of any type that has a sp...
Definition: invariant.h:437
side_effect_expr_statement_expressiont & to_side_effect_expr_statement_expression(exprt &expr)
Definition: std_code.h:1669
side_effect_expr_function_callt & to_side_effect_expr_function_call(exprt &expr)
Definition: std_code.h:1739
side_effect_expr_assignt & to_side_effect_expr_assign(exprt &expr)
Definition: std_code.h:1618
code_expressiont & to_code_expression(codet &code)
Definition: std_code.h:1428
const code_blockt & to_code_block(const codet &code)
Definition: std_code.h:203
const codet & to_code(const exprt &expr)
API to expression classes.
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:272
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition: std_expr.h:2102
const binary_exprt & to_binary_expr(const exprt &expr)
Cast an exprt to a binary_exprt.
Definition: std_expr.h:715
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition: std_expr.h:426
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition: std_types.h:308
const complex_typet & to_complex_type(const typet &type)
Cast a typet to a complex_typet.
Definition: std_types.h:1146
Symbol table entry.