CBMC
contracts.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Verify and use annotated loop and function contracts
4 
5 Author: Michael Tautschnig
6 
7 Date: February 2016
8 
9 \*******************************************************************/
10 
13 
14 #include "contracts.h"
15 
16 #include <util/c_types.h>
17 #include <util/exception_utils.h>
18 #include <util/expr_util.h>
19 #include <util/find_symbols.h>
20 #include <util/format_expr.h>
21 #include <util/fresh_symbol.h>
22 #include <util/graph.h>
23 #include <util/mathematical_expr.h>
25 #include <util/message.h>
28 #include <util/std_code.h>
29 
33 
36 #include <ansi-c/c_expr.h>
39 #include <langapi/language_util.h>
40 
41 #include "cfg_info.h"
43 #include "inlining_decorator.h"
45 #include "memory_predicates.h"
46 #include "utils.h"
47 
48 #include <algorithm>
49 #include <map>
50 
52  const irep_idt &function_name,
53  goto_functionst::goto_functiont &goto_function,
54  const local_may_aliast &local_may_alias,
55  goto_programt::targett loop_head,
56  goto_programt::targett loop_end,
57  const loopt &loop,
58  exprt assigns_clause,
59  exprt invariant,
60  exprt decreases_clause,
61  const irep_idt &mode)
62 {
63  const auto loop_head_location = loop_head->source_location();
64 
65  // Vector representing a (possibly multidimensional) decreases clause
66  const auto &decreases_clause_exprs = decreases_clause.operands();
67 
68  // Temporary variables for storing the multidimensional decreases clause
69  // at the start of and end of a loop body
70  std::vector<symbol_exprt> old_decreases_vars, new_decreases_vars;
71 
72  // replace bound variables by fresh instances
73  if(has_subexpr(invariant, ID_exists) || has_subexpr(invariant, ID_forall))
74  add_quantified_variable(invariant, mode);
75 
76  // instrument
77  //
78  // ... preamble ...
79  // HEAD:
80  // ... eval guard ...
81  // if (!guard)
82  // goto EXIT;
83  // ... loop body ...
84  // goto HEAD;
85  // EXIT:
86  // ... postamble ...
87  //
88  // to
89  //
90  // ... preamble ...
91  // ,- initialize loop_entry history vars;
92  // | entered_loop = false
93  // loop assigns check | initial_invariant_val = invariant_expr;
94  // - unchecked, temps | in_base_case = true;
95  // func assigns check | snapshot (write_set);
96  // - disabled via pragma | goto HEAD;
97  // | STEP:
98  // --. | assert (initial_invariant_val);
99  // loop assigns check | | in_base_case = false;
100  // - not applicable >======= havoc (assigns_set);
101  // func assigns check | | assume (invariant_expr);
102  // + deferred | `- old_variant_val = decreases_clause_expr;
103  // --' * HEAD:
104  // loop assigns check ,- ... eval guard ...
105  // + assertions added | if (!guard)
106  // func assigns check | goto EXIT;
107  // - disabled via pragma `- ... loop body ...
108  // ,- entered_loop = true
109  // | if (in_base_case)
110  // | goto STEP;
111  // loop assigns check | assert (invariant_expr);
112  // - unchecked, temps | new_variant_val = decreases_clause_expr;
113  // func assigns check | assert (new_variant_val < old_variant_val);
114  // - disabled via pragma | dead old_variant_val, new_variant_val;
115  // | * assume (false);
116  // | * EXIT:
117  // To be inserted at ,~~~|~~~~ assert (entered_loop ==> !in_base_case);
118  // every unique EXIT | | dead loop_entry history vars, in_base_case;
119  // (break, goto etc.) `~~~`- ~~ dead initial_invariant_val, entered_loop;
120  // ... postamble ..
121  //
122  // Asterisks (*) denote anchor points (goto targets) for instrumentations.
123  // We insert generated code above and/below these targets.
124  //
125  // Assertions for assigns clause checking are inserted in the loop body.
126 
127  // an intermediate goto_program to store generated instructions
128  // to be inserted before the loop head
129  goto_programt pre_loop_head_instrs;
130 
131  // Process "loop_entry" history variables.
132  // We find and replace all "__CPROVER_loop_entry" subexpressions in invariant.
133  std::map<exprt, exprt> history_var_map;
135  invariant,
136  history_var_map,
137  loop_head_location,
138  mode,
139  pre_loop_head_instrs,
140  ID_loop_entry);
141 
142  // Create a temporary to track if we entered the loop,
143  // i.e., the loop guard was satisfied.
144  const auto entered_loop =
146  bool_typet(), loop_head_location, mode, symbol_table, "__entered_loop")
147  .symbol_expr();
148  pre_loop_head_instrs.add(
149  goto_programt::make_decl(entered_loop, loop_head_location));
150  pre_loop_head_instrs.add(
152 
153  // Create a snapshot of the invariant so that we can check the base case,
154  // if the loop is not vacuous and must be abstracted with contracts.
155  const auto initial_invariant_val =
157  bool_typet(), loop_head_location, mode, symbol_table, "__init_invariant")
158  .symbol_expr();
159  pre_loop_head_instrs.add(
160  goto_programt::make_decl(initial_invariant_val, loop_head_location));
161  {
162  // Although the invariant at this point will not have side effects,
163  // it is still a C expression, and needs to be "goto_convert"ed.
164  // Note that this conversion may emit many GOTO instructions.
165  code_assignt initial_invariant_value_assignment{
166  initial_invariant_val, invariant};
167  initial_invariant_value_assignment.add_source_location() =
168  loop_head_location;
170  initial_invariant_value_assignment, pre_loop_head_instrs, mode);
171  }
172 
173  // Create a temporary variable to track base case vs inductive case
174  // instrumentation of the loop.
175  const auto in_base_case =
177  bool_typet(), loop_head_location, mode, symbol_table, "__in_base_case")
178  .symbol_expr();
179  pre_loop_head_instrs.add(
180  goto_programt::make_decl(in_base_case, loop_head_location));
181  pre_loop_head_instrs.add(
182  goto_programt::make_assignment(in_base_case, true_exprt{}));
183 
184  // CAR snapshot instructions for checking assigns clause
185  goto_programt snapshot_instructions;
186 
187  loop_cfg_infot cfg_info(goto_function, loop);
188 
189  // track static local symbols
190  instrument_spec_assignst instrument_spec_assigns(
191  function_name,
193  cfg_info,
194  symbol_table,
196 
197  instrument_spec_assigns.track_static_locals_between(
198  loop_head, loop_end, snapshot_instructions);
199 
200  // set of targets to havoc
201  assignst to_havoc;
202 
203  if(assigns_clause.is_nil())
204  {
205  // No assigns clause was specified for this loop.
206  // Infer memory locations assigned by the loop from the loop instructions
207  // and the inferred aliasing relation.
208  try
209  {
210  get_assigns(local_may_alias, loop, to_havoc);
211  // TODO: if the set contains pairs (i, a[i]),
212  // we must at least widen them to (i, pointer_object(a))
213 
214  // remove loop-local symbols from the inferred set
215  cfg_info.erase_locals(to_havoc);
216 
217  log.debug() << "No loop assigns clause provided. Inferred targets: {";
218  // Add inferred targets to the loop assigns clause.
219  bool ran_once = false;
220  for(const auto &target : to_havoc)
221  {
222  if(ran_once)
223  log.debug() << ", ";
224  ran_once = true;
225  log.debug() << format(target);
226  instrument_spec_assigns.track_spec_target(
227  target, snapshot_instructions);
228  }
229  log.debug() << "}" << messaget::eom;
230 
231  instrument_spec_assigns.get_static_locals(
232  std::inserter(to_havoc, to_havoc.end()));
233  }
234  catch(const analysis_exceptiont &exc)
235  {
236  log.error() << "Failed to infer variables being modified by the loop at "
237  << loop_head_location
238  << ".\nPlease specify an assigns clause.\nReason:"
239  << messaget::eom;
240  throw exc;
241  }
242  }
243  else
244  {
245  // An assigns clause was specified for this loop.
246  // Add the targets to the set of expressions to havoc.
247  for(const auto &target : assigns_clause.operands())
248  {
249  to_havoc.insert(target);
250  instrument_spec_assigns.track_spec_target(target, snapshot_instructions);
251  }
252  }
253 
254  // Insert instrumentation
255  // This must be done before havocing the write set.
256  // FIXME: this is not true for write set targets that
257  // might depend on other write set targets.
258  pre_loop_head_instrs.destructive_append(snapshot_instructions);
259 
260  // Insert a jump to the loop head
261  // (skipping over the step case initialization code below)
262  pre_loop_head_instrs.add(
263  goto_programt::make_goto(loop_head, true_exprt{}, loop_head_location));
264 
265  // The STEP case instructions follow.
266  // We skip past it initially, because of the unconditional jump above,
267  // but jump back here if we get past the loop guard while in_base_case.
268 
269  const auto step_case_target =
270  pre_loop_head_instrs.add(goto_programt::make_assignment(
271  in_base_case, false_exprt{}, loop_head_location));
272 
273  // If we jump here, then the loop runs at least once,
274  // so add the base case assertion:
275  // assert(initial_invariant_val)
276  // We use a block scope for assertion, since it's immediately goto converted,
277  // and doesn't need to be kept around.
278  {
279  code_assertt assertion{initial_invariant_val};
280  assertion.add_source_location() = loop_head_location;
281  converter.goto_convert(assertion, pre_loop_head_instrs, mode);
282  pre_loop_head_instrs.instructions.back()
283  .source_location_nonconst()
284  .set_comment("Check loop invariant before entry");
285  }
286 
287  // Insert the first block of pre_loop_head_instrs,
288  // with a pragma to disable assigns clause checking.
289  // All of the initialization code so far introduces local temporaries,
290  // which need not be checked against the enclosing scope's assigns clause.
291  goto_function.body.destructive_insert(
292  loop_head, add_pragma_disable_assigns_check(pre_loop_head_instrs));
293 
294  // Generate havocing code for assignment targets.
295  havoc_assigns_targetst havoc_gen(to_havoc, ns);
296  havoc_gen.append_full_havoc_code(loop_head_location, pre_loop_head_instrs);
297 
298  // Insert the second block of pre_loop_head_instrs: the havocing code.
299  // We do not `add_pragma_disable_assigns_check`,
300  // so that the enclosing scope's assigns clause instrumentation
301  // would pick these havocs up for inclusion (subset) checks.
302  goto_function.body.destructive_insert(loop_head, pre_loop_head_instrs);
303 
304  // Generate: assume(invariant) just after havocing
305  // We use a block scope for assumption, since it's immediately goto converted,
306  // and doesn't need to be kept around.
307  {
308  code_assumet assumption{invariant};
309  assumption.add_source_location() = loop_head_location;
310  converter.goto_convert(assumption, pre_loop_head_instrs, mode);
311  }
312 
313  // Create fresh temporary variables that store the multidimensional
314  // decreases clause's value before and after the loop
315  for(const auto &clause : decreases_clause.operands())
316  {
317  const auto old_decreases_var =
318  new_tmp_symbol(clause.type(), loop_head_location, mode, symbol_table)
319  .symbol_expr();
320  pre_loop_head_instrs.add(
321  goto_programt::make_decl(old_decreases_var, loop_head_location));
322  old_decreases_vars.push_back(old_decreases_var);
323 
324  const auto new_decreases_var =
325  new_tmp_symbol(clause.type(), loop_head_location, mode, symbol_table)
326  .symbol_expr();
327  pre_loop_head_instrs.add(
328  goto_programt::make_decl(new_decreases_var, loop_head_location));
329  new_decreases_vars.push_back(new_decreases_var);
330  }
331 
332  // TODO: Fix loop contract handling for do/while loops.
333  if(loop_end->is_goto() && !loop_end->condition().is_true())
334  {
335  log.error() << "Loop contracts are unsupported on do/while loops: "
336  << loop_head_location << messaget::eom;
337  throw 0;
338 
339  // non-deterministically skip the loop if it is a do-while loop.
340  // pre_loop_head_instrs.add(goto_programt::make_goto(
341  // loop_end, side_effect_expr_nondett(bool_typet(), loop_head_location)));
342  }
343 
344  // Generate: assignments to store the multidimensional decreases clause's
345  // value just before the loop_head
346  if(!decreases_clause.is_nil())
347  {
348  for(size_t i = 0; i < old_decreases_vars.size(); i++)
349  {
350  code_assignt old_decreases_assignment{
351  old_decreases_vars[i], decreases_clause_exprs[i]};
352  old_decreases_assignment.add_source_location() = loop_head_location;
354  old_decreases_assignment, pre_loop_head_instrs, mode);
355  }
356 
357  goto_function.body.destructive_insert(
358  loop_head, add_pragma_disable_assigns_check(pre_loop_head_instrs));
359  }
360 
361  // Insert the third and final block of pre_loop_head_instrs,
362  // with a pragma to disable assigns clause checking.
363  // The variables to store old variant value are local temporaries,
364  // which need not be checked against the enclosing scope's assigns clause.
365  goto_function.body.destructive_insert(
366  loop_head, add_pragma_disable_assigns_check(pre_loop_head_instrs));
367 
368  // Perform write set instrumentation on the entire loop.
369  instrument_spec_assigns.instrument_instructions(
370  goto_function.body,
371  loop_head,
372  loop_end,
373  [&loop](const goto_programt::targett &t) { return loop.contains(t); });
374 
375  // Now we begin instrumenting at the loop_end.
376  // `pre_loop_end_instrs` are to be inserted before `loop_end`.
377  goto_programt pre_loop_end_instrs;
378 
379  // Record that we entered the loop.
380  pre_loop_end_instrs.add(
381  goto_programt::make_assignment(entered_loop, true_exprt{}));
382 
383  // Jump back to the step case to havoc the write set, assume the invariant,
384  // and execute an arbitrary iteration.
385  pre_loop_end_instrs.add(goto_programt::make_goto(
386  step_case_target, in_base_case, loop_head_location));
387 
388  // The following code is only reachable in the step case,
389  // i.e., when in_base_case == false,
390  // because of the unconditional jump above.
391 
392  // Generate the inductiveness check:
393  // assert(invariant)
394  // We use a block scope for assertion, since it's immediately goto converted,
395  // and doesn't need to be kept around.
396  {
397  code_assertt assertion{invariant};
398  assertion.add_source_location() = loop_head_location;
399  converter.goto_convert(assertion, pre_loop_end_instrs, mode);
400  pre_loop_end_instrs.instructions.back()
401  .source_location_nonconst()
402  .set_comment("Check that loop invariant is preserved");
403  }
404 
405  // Generate: assignments to store the multidimensional decreases clause's
406  // value after one iteration of the loop
407  if(!decreases_clause.is_nil())
408  {
409  for(size_t i = 0; i < new_decreases_vars.size(); i++)
410  {
411  code_assignt new_decreases_assignment{
412  new_decreases_vars[i], decreases_clause_exprs[i]};
413  new_decreases_assignment.add_source_location() = loop_head_location;
415  new_decreases_assignment, pre_loop_end_instrs, mode);
416  }
417 
418  // Generate: assertion that the multidimensional decreases clause's value
419  // after the loop is lexicographically smaller than its initial value.
420  code_assertt monotonic_decreasing_assertion{
422  new_decreases_vars, old_decreases_vars)};
423  monotonic_decreasing_assertion.add_source_location() = loop_head_location;
425  monotonic_decreasing_assertion, pre_loop_end_instrs, mode);
426  pre_loop_end_instrs.instructions.back()
427  .source_location_nonconst()
428  .set_comment("Check decreases clause on loop iteration");
429 
430  // Discard the temporary variables that store decreases clause's value
431  for(size_t i = 0; i < old_decreases_vars.size(); i++)
432  {
433  pre_loop_end_instrs.add(
434  goto_programt::make_dead(old_decreases_vars[i], loop_head_location));
435  pre_loop_end_instrs.add(
436  goto_programt::make_dead(new_decreases_vars[i], loop_head_location));
437  }
438  }
439 
441  goto_function.body,
442  loop_end,
443  add_pragma_disable_assigns_check(pre_loop_end_instrs));
444 
445  // change the back edge into assume(false) or assume(guard)
446  loop_end->turn_into_assume();
447  loop_end->condition_nonconst() = boolean_negate(loop_end->condition());
448 
449  std::set<goto_programt::targett> seen_targets;
450  // Find all exit points of the loop, make temporary variables `DEAD`,
451  // and check that step case was checked for non-vacuous loops.
452  for(const auto &t : loop)
453  {
454  if(!t->is_goto())
455  continue;
456 
457  auto exit_target = t->get_target();
458  if(
459  loop.contains(exit_target) ||
460  seen_targets.find(exit_target) != seen_targets.end())
461  continue;
462 
463  seen_targets.insert(exit_target);
464 
465  goto_programt pre_loop_exit_instrs;
466  // Assertion to check that step case was checked if we entered the loop.
467  pre_loop_exit_instrs.add(goto_programt::make_assertion(
468  or_exprt{not_exprt{entered_loop}, not_exprt{in_base_case}},
469  loop_head_location));
470  pre_loop_exit_instrs.instructions.back()
471  .source_location_nonconst()
472  .set_comment("Check that loop instrumentation was not truncated");
473  // Instructions to make all the temporaries go dead.
474  pre_loop_exit_instrs.add(
475  goto_programt::make_dead(in_base_case, loop_head_location));
476  pre_loop_exit_instrs.add(
477  goto_programt::make_dead(initial_invariant_val, loop_head_location));
478  for(const auto &v : history_var_map)
479  {
480  pre_loop_exit_instrs.add(
481  goto_programt::make_dead(to_symbol_expr(v.second), loop_head_location));
482  }
483  // Insert these instructions, preserving the loop end target.
485  goto_function.body, exit_target, pre_loop_exit_instrs);
486  }
487 }
488 
490  exprt &expression,
491  const irep_idt &mode)
492 {
493  if(expression.id() == ID_not || expression.id() == ID_typecast)
494  {
495  // For unary connectives, recursively check for
496  // nested quantified formulae in the term
497  auto &unary_expression = to_unary_expr(expression);
498  add_quantified_variable(unary_expression.op(), mode);
499  }
500  if(expression.id() == ID_notequal || expression.id() == ID_implies)
501  {
502  // For binary connectives, recursively check for
503  // nested quantified formulae in the left and right terms
504  auto &binary_expression = to_binary_expr(expression);
505  add_quantified_variable(binary_expression.lhs(), mode);
506  add_quantified_variable(binary_expression.rhs(), mode);
507  }
508  if(expression.id() == ID_if)
509  {
510  // For ternary connectives, recursively check for
511  // nested quantified formulae in all three terms
512  auto &if_expression = to_if_expr(expression);
513  add_quantified_variable(if_expression.cond(), mode);
514  add_quantified_variable(if_expression.true_case(), mode);
515  add_quantified_variable(if_expression.false_case(), mode);
516  }
517  if(expression.id() == ID_and || expression.id() == ID_or)
518  {
519  // For multi-ary connectives, recursively check for
520  // nested quantified formulae in all terms
521  auto &multi_ary_expression = to_multi_ary_expr(expression);
522  for(auto &operand : multi_ary_expression.operands())
523  {
524  add_quantified_variable(operand, mode);
525  }
526  }
527  else if(expression.id() == ID_exists || expression.id() == ID_forall)
528  {
529  // When a quantifier expression is found, create a fresh symbol for each
530  // quantified variable and rewrite the expression to use those fresh
531  // symbols.
532  auto &quantifier_expression = to_quantifier_expr(expression);
533  std::vector<symbol_exprt> fresh_variables;
534  fresh_variables.reserve(quantifier_expression.variables().size());
535  for(const auto &quantified_variable : quantifier_expression.variables())
536  {
537  // 1. create fresh symbol
538  symbolt new_symbol = new_tmp_symbol(
539  quantified_variable.type(),
540  quantified_variable.source_location(),
541  mode,
542  symbol_table);
543 
544  // 2. add created fresh symbol to expression map
545  fresh_variables.push_back(new_symbol.symbol_expr());
546  }
547 
548  // use fresh symbols
549  exprt where = quantifier_expression.instantiate(fresh_variables);
550 
551  // recursively check for nested quantified formulae
552  add_quantified_variable(where, mode);
553 
554  // replace previous variables and body
555  quantifier_expression.variables() = fresh_variables;
556  quantifier_expression.where() = std::move(where);
557  }
558 }
559 
561  exprt &expr,
562  std::map<exprt, exprt> &parameter2history,
563  source_locationt location,
564  const irep_idt &mode,
565  goto_programt &history,
566  const irep_idt &id)
567 {
568  for(auto &op : expr.operands())
569  {
571  op, parameter2history, location, mode, history, id);
572  }
573 
574  if(expr.id() == ID_old || expr.id() == ID_loop_entry)
575  {
576  const auto &parameter = to_history_expr(expr, id).expression();
577 
578  const auto &id = parameter.id();
579  if(
580  id == ID_dereference || id == ID_member || id == ID_symbol ||
581  id == ID_ptrmember || id == ID_constant || id == ID_typecast ||
582  id == ID_index)
583  {
584  auto it = parameter2history.find(parameter);
585 
586  if(it == parameter2history.end())
587  {
588  // 0. Create a skip target to jump to, if the parameter is invalid
589  goto_programt skip_program;
590  const auto skip_target =
591  skip_program.add(goto_programt::make_skip(location));
592 
593  // 1. Create a temporary symbol expression that represents the
594  // history variable
595  symbol_exprt tmp_symbol =
596  new_tmp_symbol(parameter.type(), location, mode, symbol_table)
597  .symbol_expr();
598 
599  // 2. Associate the above temporary variable to it's corresponding
600  // expression
601  parameter2history[parameter] = tmp_symbol;
602 
603  // 3. Add the required instructions to the instructions list
604  // 3.1. Declare the newly created temporary variable
605  history.add(goto_programt::make_decl(tmp_symbol, location));
606 
607  // 3.2. Skip storing the history if the expression is invalid
609  skip_target,
611  location));
612 
613  // 3.3. Add an assignment such that the value pointed to by the new
614  // temporary variable is equal to the value of the corresponding
615  // parameter
616  history.add(
617  goto_programt::make_assignment(tmp_symbol, parameter, location));
618 
619  // 3.4. Add a skip target
620  history.destructive_append(skip_program);
621  }
622 
623  expr = parameter2history[parameter];
624  }
625  else
626  {
627  log.error() << "Tracking history of " << parameter.id()
628  << " expressions is not supported yet." << messaget::eom;
629  throw 0;
630  }
631  }
632 }
633 
634 std::pair<goto_programt, goto_programt>
636  codet &expression,
637  source_locationt location,
638  const irep_idt &mode)
639 {
640  std::map<exprt, exprt> parameter2history;
641  goto_programt history;
642 
643  // Find and replace "old" expression in the "expression" variable
645  expression, parameter2history, location, mode, history, ID_old);
646 
647  // Create instructions corresponding to the ensures clause
648  goto_programt ensures_program;
649  converter.goto_convert(expression, ensures_program, mode);
650 
651  // return a pair containing:
652  // 1. instructions corresponding to the ensures clause
653  // 2. instructions related to initializing the history variables
654  return std::make_pair(std::move(ensures_program), std::move(history));
655 }
656 
657 static const code_with_contract_typet &
658 get_contract(const irep_idt &function, const namespacet &ns)
659 {
660  const std::string &function_str = id2string(function);
661  const auto &function_symbol = ns.lookup(function);
662 
663  const symbolt *contract_sym;
664  if(ns.lookup("contract::" + function_str, contract_sym))
665  {
666  // no contract provided in the source or just an empty assigns clause
667  return to_code_with_contract_type(function_symbol.type);
668  }
669 
670  const auto &type = to_code_with_contract_type(contract_sym->type);
671  if(type != function_symbol.type)
672  {
674  "Contract of '" + function_str + "' has different signature.");
675  }
676 
677  return type;
678 }
679 
681  const irep_idt &function,
682  const source_locationt &location,
683  goto_programt &function_body,
684  goto_programt::targett &target)
685 {
686  const auto &const_target =
687  static_cast<const goto_programt::targett &>(target);
688  // Return if the function is not named in the call; currently we don't handle
689  // function pointers.
690  PRECONDITION(const_target->call_function().id() == ID_symbol);
691 
692  const irep_idt &target_function =
693  to_symbol_expr(const_target->call_function()).get_identifier();
694  const symbolt &function_symbol = ns.lookup(target_function);
695  const code_typet &function_type = to_code_type(function_symbol.type);
696 
697  // Isolate each component of the contract.
698  const auto &type = get_contract(target_function, ns);
699  auto assigns_clause = type.assigns();
700  auto requires_contract = type.requires_contract();
701  auto ensures_contract = type.ensures_contract();
702 
703  // Prepare to instantiate expressions in the callee
704  // with expressions from the call site (e.g. the return value).
705  exprt::operandst instantiation_values;
706 
707  // keep track of the call's return expression to make it nondet later
708  optionalt<exprt> call_ret_opt = {};
709 
710  // if true, the call return variable variable was created during replacement
711  bool call_ret_is_fresh_var = false;
712 
713  if(function_type.return_type() != empty_typet())
714  {
715  // Check whether the function's return value is not disregarded.
716  if(target->call_lhs().is_not_nil())
717  {
718  // If so, have it replaced appropriately.
719  // For example, if foo() ensures that its return value is > 5, then
720  // rewrite calls to foo as follows:
721  // x = foo() -> assume(__CPROVER_return_value > 5) -> assume(x > 5)
722  auto &lhs_expr = const_target->call_lhs();
723  call_ret_opt = lhs_expr;
724  instantiation_values.push_back(lhs_expr);
725  }
726  else
727  {
728  // If the function does return a value, but the return value is
729  // disregarded, check if the postcondition includes the return value.
730  if(std::any_of(
731  type.ensures().begin(), type.ensures().end(), [](const exprt &e) {
732  return has_symbol_expr(
733  to_lambda_expr(e).where(), CPROVER_PREFIX "return_value", true);
734  }))
735  {
736  // The postcondition does mention __CPROVER_return_value, so mint a
737  // fresh variable to replace __CPROVER_return_value with.
738  call_ret_is_fresh_var = true;
739  const symbolt &fresh = get_fresh_aux_symbol(
740  function_type.return_type(),
741  id2string(target_function),
742  "ignored_return_value",
743  const_target->source_location(),
744  symbol_table.lookup_ref(target_function).mode,
745  ns,
746  symbol_table);
747  auto fresh_sym_expr = fresh.symbol_expr();
748  call_ret_opt = fresh_sym_expr;
749  instantiation_values.push_back(fresh_sym_expr);
750  }
751  else
752  {
753  // unused, add a dummy with the right type
754  instantiation_values.push_back(
755  exprt{ID_nil, function_type.return_type()});
756  }
757  }
758  }
759 
760  // Replace formal parameters
761  const auto &arguments = const_target->call_arguments();
762  instantiation_values.insert(
763  instantiation_values.end(), arguments.begin(), arguments.end());
764 
765  const auto &mode = function_symbol.mode;
766 
767  // new program where all contract-derived instructions are added
768  goto_programt new_program;
769 
770  is_fresh_replacet is_fresh(*this, log, target_function);
771  is_fresh.create_declarations();
772  is_fresh.add_memory_map_decl(new_program);
773 
774  // Insert assertion of the precondition immediately before the call site.
775  exprt::operandst requires_conjuncts;
776  for(const auto &r : type.requires())
777  {
778  requires_conjuncts.push_back(
779  to_lambda_expr(r).application(instantiation_values));
780  }
781  auto requires = conjunction(requires_conjuncts);
782  requires.add_source_location() =
783  requires_conjuncts.empty() ? type.source_location()
784  : type.requires().front().source_location();
785  if(!requires.is_true())
786  {
787  if(has_subexpr(requires, ID_exists) || has_subexpr(requires, ID_forall))
788  add_quantified_variable(requires, mode);
789 
790  goto_programt assertion;
791  converter.goto_convert(code_assertt(requires), assertion, mode);
792  assertion.instructions.back().source_location_nonconst() =
793  requires.source_location();
794  assertion.instructions.back().source_location_nonconst().set_comment(
795  "Check requires clause");
796  assertion.instructions.back().source_location_nonconst().set_property_class(
797  ID_precondition);
798  is_fresh.update_requires(assertion);
799  new_program.destructive_append(assertion);
800  }
801 
802  // Translate requires_contract(ptr, contract) clauses to assertions
803  for(auto &expr : requires_contract)
804  {
807  to_lambda_expr(expr).application(instantiation_values)),
808  ID_precondition,
809  mode,
810  new_program);
811  }
812 
813  // Gather all the instructions required to handle history variables
814  // as well as the ensures clause
815  exprt::operandst ensures_conjuncts;
816  for(const auto &r : type.ensures())
817  {
818  ensures_conjuncts.push_back(
819  to_lambda_expr(r).application(instantiation_values));
820  }
821  auto ensures = conjunction(ensures_conjuncts);
822  ensures.add_source_location() = ensures_conjuncts.empty()
823  ? type.source_location()
824  : type.ensures().front().source_location();
825  std::pair<goto_programt, goto_programt> ensures_pair;
826  if(!ensures.is_false())
827  {
828  if(has_subexpr(ensures, ID_exists) || has_subexpr(ensures, ID_forall))
829  add_quantified_variable(ensures, mode);
830 
831  auto assumption = code_assumet(ensures);
832  ensures_pair =
833  create_ensures_instruction(assumption, ensures.source_location(), mode);
834 
835  // add all the history variable initialization instructions
836  new_program.destructive_append(ensures_pair.second);
837  }
838 
839  // ASSIGNS clause should not refer to any quantified variables,
840  // and only refer to the common symbols to be replaced.
841  exprt::operandst targets;
842  for(auto &target : assigns_clause)
843  targets.push_back(to_lambda_expr(target).application(instantiation_values));
844 
845  // Create a sequence of non-deterministic assignments ...
846 
847  // ... for the assigns clause targets and static locals
848  goto_programt havoc_instructions;
849  function_cfg_infot cfg_info({});
851  target_function,
852  targets,
854  cfg_info,
855  location,
856  symbol_table,
858 
859  havocker.get_instructions(havoc_instructions);
860 
861  // ... for the return value
862  if(call_ret_opt.has_value())
863  {
864  auto &call_ret = call_ret_opt.value();
865  auto &loc = call_ret.source_location();
866  auto &type = call_ret.type();
867 
868  // Declare if fresh
869  if(call_ret_is_fresh_var)
870  havoc_instructions.add(
871  goto_programt::make_decl(to_symbol_expr(call_ret), loc));
872 
873  side_effect_expr_nondett expr(type, location);
874  auto target = havoc_instructions.add(
875  goto_programt::make_assignment(call_ret, expr, loc));
876  target->code_nonconst().add_source_location() = loc;
877  }
878 
879  // Insert havoc instructions immediately before the call site.
880  new_program.destructive_append(havoc_instructions);
881 
882  // To remove the function call, insert statements related to the assumption.
883  // Then, replace the function call with a SKIP statement.
884  if(!ensures.is_false())
885  {
886  is_fresh.update_ensures(ensures_pair.first);
887  new_program.destructive_append(ensures_pair.first);
888  }
889 
890  // Translate ensures_contract(ptr, contract) clauses to assumptions
891  for(auto &expr : ensures_contract)
892  {
895  to_lambda_expr(expr).application(instantiation_values)),
896  mode,
897  new_program);
898  }
899 
900  // Kill return value variable if fresh
901  if(call_ret_is_fresh_var)
902  {
904  log.warning(), [&target](messaget::mstreamt &mstream) {
905  target->output(mstream);
906  mstream << messaget::eom;
907  });
908  auto dead_inst =
909  goto_programt::make_dead(to_symbol_expr(call_ret_opt.value()), location);
910  function_body.insert_before_swap(target, dead_inst);
911  ++target;
912  }
913 
914  is_fresh.add_memory_map_dead(new_program);
915 
916  // Erase original function call
917  *target = goto_programt::make_skip();
918 
919  // insert contract replacement instructions
920  insert_before_swap_and_advance(function_body, target, new_program);
921 
922  // Add this function to the set of replaced functions.
923  summarized.insert(target_function);
924 
925  // restore global goto_program consistency
927 }
928 
930  const irep_idt &function_name,
931  goto_functionst::goto_functiont &goto_function)
932 {
933  const bool may_have_loops = std::any_of(
934  goto_function.body.instructions.begin(),
935  goto_function.body.instructions.end(),
936  [](const goto_programt::instructiont &instruction) {
937  return instruction.is_backwards_goto();
938  });
939 
940  if(!may_have_loops)
941  return;
942 
945  goto_functions, function_name, ns, log.get_message_handler());
946 
947  INVARIANT(
948  decorated.get_recursive_call_set().size() == 0,
949  "Recursive functions found during inlining");
950 
951  // restore internal invariants
953 
954  local_may_aliast local_may_alias(goto_function);
955  natural_loops_mutablet natural_loops(goto_function.body);
956 
957  // A graph node type that stores information about a loop.
958  // We create a DAG representing nesting of various loops in goto_function,
959  // sort them topologically, and instrument them in the top-sorted order.
960  //
961  // The goal here is not avoid explicit "subset checks" on nested write sets.
962  // When instrumenting in a top-sorted order,
963  // the outer loop would no longer observe the inner loop's write set,
964  // but only corresponding `havoc` statements,
965  // which can be instrumented in the usual way to achieve a "subset check".
966 
967  struct loop_graph_nodet : public graph_nodet<empty_edget>
968  {
969  const typename natural_loops_mutablet::loopt &content;
970  const goto_programt::targett head_target, end_target;
971  exprt assigns_clause, invariant, decreases_clause;
972 
973  loop_graph_nodet(
974  const typename natural_loops_mutablet::loopt &loop,
975  const goto_programt::targett head,
976  const goto_programt::targett end,
977  const exprt &assigns,
978  const exprt &inv,
979  const exprt &decreases)
980  : content(loop),
981  head_target(head),
982  end_target(end),
983  assigns_clause(assigns),
984  invariant(inv),
985  decreases_clause(decreases)
986  {
987  }
988  };
989  grapht<loop_graph_nodet> loop_nesting_graph;
990 
991  std::list<size_t> to_check_contracts_on_children;
992 
993  for(const auto &loop_head_and_content : natural_loops.loop_map)
994  {
995  const auto &loop_content = loop_head_and_content.second;
996  if(loop_content.empty())
997  continue;
998 
999  auto loop_head = loop_head_and_content.first;
1000  auto loop_end = loop_head;
1001 
1002  // Find the last back edge to `loop_head`
1003  for(const auto &t : loop_content)
1004  {
1005  if(
1006  t->is_goto() && t->get_target() == loop_head &&
1007  t->location_number > loop_end->location_number)
1008  loop_end = t;
1009  }
1010 
1011  if(loop_end == loop_head)
1012  {
1013  log.error() << "Could not find end of the loop starting at: "
1014  << loop_head->source_location() << messaget::eom;
1015  throw 0;
1016  }
1017 
1018  exprt assigns_clause =
1019  static_cast<const exprt &>(loop_end->condition().find(ID_C_spec_assigns));
1020  exprt invariant = static_cast<const exprt &>(
1021  loop_end->condition().find(ID_C_spec_loop_invariant));
1022  exprt decreases_clause = static_cast<const exprt &>(
1023  loop_end->condition().find(ID_C_spec_decreases));
1024 
1025  if(invariant.is_nil())
1026  {
1027  if(decreases_clause.is_not_nil() || assigns_clause.is_not_nil())
1028  {
1029  invariant = true_exprt{};
1030  // assigns clause is missing; we will try to automatic inference
1031  log.warning()
1032  << "The loop at " << loop_head->source_location().as_string()
1033  << " does not have an invariant in its contract.\n"
1034  << "Hence, a default invariant ('true') is being used.\n"
1035  << "This choice is sound, but verification may fail"
1036  << " if it is be too weak to prove the desired properties."
1037  << messaget::eom;
1038  }
1039  }
1040  else
1041  {
1042  invariant = conjunction(invariant.operands());
1043  if(decreases_clause.is_nil())
1044  {
1045  log.warning() << "The loop at "
1046  << loop_head->source_location().as_string()
1047  << " does not have a decreases clause in its contract.\n"
1048  << "Termination of this loop will not be verified."
1049  << messaget::eom;
1050  }
1051  }
1052 
1053  const auto idx = loop_nesting_graph.add_node(
1054  loop_content,
1055  loop_head,
1056  loop_end,
1057  assigns_clause,
1058  invariant,
1059  decreases_clause);
1060 
1061  if(
1062  assigns_clause.is_nil() && invariant.is_nil() &&
1063  decreases_clause.is_nil())
1064  continue;
1065 
1066  to_check_contracts_on_children.push_back(idx);
1067 
1068  // By definition the `loop_content` is a set of instructions computed
1069  // by `natural_loops` based on the CFG.
1070  // Since we perform assigns clause instrumentation by sequentially
1071  // traversing instructions from `loop_head` to `loop_end`,
1072  // here we ensure that all instructions in `loop_content` belong within
1073  // the [loop_head, loop_end] target range
1074 
1075  // Check 1. (i \in loop_content) ==> loop_head <= i <= loop_end
1076  for(const auto &i : loop_content)
1077  {
1078  if(std::distance(loop_head, i) < 0 || std::distance(i, loop_end) < 0)
1079  {
1081  log.error(), [&i, &loop_head](messaget::mstreamt &mstream) {
1082  mstream << "Computed loop at " << loop_head->source_location()
1083  << "contains an instruction beyond [loop_head, loop_end]:"
1084  << messaget::eom;
1085  i->output(mstream);
1086  mstream << messaget::eom;
1087  });
1088  throw 0;
1089  }
1090  }
1091  }
1092 
1093  for(size_t outer = 0; outer < loop_nesting_graph.size(); ++outer)
1094  {
1095  for(size_t inner = 0; inner < loop_nesting_graph.size(); ++inner)
1096  {
1097  if(inner == outer)
1098  continue;
1099 
1100  if(loop_nesting_graph[outer].content.contains(
1101  loop_nesting_graph[inner].head_target))
1102  {
1103  if(!loop_nesting_graph[outer].content.contains(
1104  loop_nesting_graph[inner].end_target))
1105  {
1106  log.error()
1107  << "Overlapping loops at:\n"
1108  << loop_nesting_graph[outer].head_target->source_location()
1109  << "\nand\n"
1110  << loop_nesting_graph[inner].head_target->source_location()
1111  << "\nLoops must be nested or sequential for contracts to be "
1112  "enforced."
1113  << messaget::eom;
1114  }
1115  loop_nesting_graph.add_edge(inner, outer);
1116  }
1117  }
1118  }
1119 
1120  // make sure all children of a contractified loop also have contracts
1121  while(!to_check_contracts_on_children.empty())
1122  {
1123  const auto loop_idx = to_check_contracts_on_children.front();
1124  to_check_contracts_on_children.pop_front();
1125 
1126  const auto &loop_node = loop_nesting_graph[loop_idx];
1127  if(
1128  loop_node.assigns_clause.is_nil() && loop_node.invariant.is_nil() &&
1129  loop_node.decreases_clause.is_nil())
1130  {
1131  log.error()
1132  << "Inner loop at: " << loop_node.head_target->source_location()
1133  << " does not have contracts, but an enclosing loop does.\n"
1134  << "Please provide contracts for this loop, or unwind it first."
1135  << messaget::eom;
1136  throw 0;
1137  }
1138 
1139  for(const auto child_idx : loop_nesting_graph.get_predecessors(loop_idx))
1140  to_check_contracts_on_children.push_back(child_idx);
1141  }
1142 
1143  // Iterate over the (natural) loops in the function, in topo-sorted order,
1144  // and apply any loop contracts that we find.
1145  for(const auto &idx : loop_nesting_graph.topsort())
1146  {
1147  const auto &loop_node = loop_nesting_graph[idx];
1148  if(
1149  loop_node.assigns_clause.is_nil() && loop_node.invariant.is_nil() &&
1150  loop_node.decreases_clause.is_nil())
1151  continue;
1152 
1153  // Computed loop "contents" needs to be refreshed to include any newly
1154  // introduced instrumentation, e.g. havoc instructions for assigns clause,
1155  // on inner loops in to the outer loop's contents.
1156  // Else, during the outer loop instrumentation these instructions will be
1157  // "masked" just as any other instruction not within its "contents."
1158 
1160  natural_loops_mutablet updated_loops(goto_function.body);
1161 
1163  function_name,
1164  goto_function,
1165  local_may_alias,
1166  loop_node.head_target,
1167  loop_node.end_target,
1168  updated_loops.loop_map[loop_node.head_target],
1169  loop_node.assigns_clause,
1170  loop_node.invariant,
1171  loop_node.decreases_clause,
1172  symbol_table.lookup_ref(function_name).mode);
1173  }
1174 }
1175 
1177 {
1178  return symbol_table;
1179 }
1180 
1182 {
1183  return goto_functions;
1184 }
1185 
1187 {
1188  // Get the function object before instrumentation.
1189  auto function_obj = goto_functions.function_map.find(function);
1190 
1191  INVARIANT(
1192  function_obj != goto_functions.function_map.end(),
1193  "Function '" + id2string(function) + "'must exist in the goto program");
1194 
1195  const auto &goto_function = function_obj->second;
1196  auto &function_body = function_obj->second.body;
1197 
1198  function_cfg_infot cfg_info(goto_function);
1199 
1200  instrument_spec_assignst instrument_spec_assigns(
1201  function,
1203  cfg_info,
1204  symbol_table,
1206 
1207  // Detect and track static local variables before inlining
1208  goto_programt snapshot_static_locals;
1209  instrument_spec_assigns.track_static_locals(snapshot_static_locals);
1210 
1211  // Full inlining of the function body
1212  // Inlining is performed so that function calls to a same function
1213  // occurring under different write sets get instrumented specifically
1214  // for each write set
1216  goto_function_inline(goto_functions, function, ns, decorated);
1217 
1218  decorated.throw_on_recursive_calls(log, 0);
1219 
1220  // Clean up possible fake loops that are due to `IF 0!=0 GOTO i` instructions
1221  simplify_gotos(function_body, ns);
1222 
1223  // Restore internal coherence in the programs
1225 
1226  INVARIANT(
1227  is_loop_free(function_body, ns, log),
1228  "Loops remain in function '" + id2string(function) +
1229  "', assigns clause checking instrumentation cannot be applied.");
1230 
1231  // Start instrumentation
1232  auto instruction_it = function_body.instructions.begin();
1233 
1234  // Inject local static snapshots
1236  function_body, instruction_it, snapshot_static_locals);
1237 
1238  // Track targets mentioned in the specification
1239  const symbolt &function_symbol = ns.lookup(function);
1240  const code_typet &function_type = to_code_type(function_symbol.type);
1241  exprt::operandst instantiation_values;
1242  // assigns clauses cannot refer to the return value, but we still need an
1243  // element in there to apply the lambda function consistently
1244  if(function_type.return_type() != empty_typet())
1245  instantiation_values.push_back(exprt{ID_nil, function_type.return_type()});
1246  for(const auto &param : function_type.parameters())
1247  {
1248  instantiation_values.push_back(
1249  ns.lookup(param.get_identifier()).symbol_expr());
1250  }
1251  for(auto &target : get_contract(function, ns).assigns())
1252  {
1253  goto_programt payload;
1254  instrument_spec_assigns.track_spec_target(
1255  to_lambda_expr(target).application(instantiation_values), payload);
1256  insert_before_swap_and_advance(function_body, instruction_it, payload);
1257  }
1258 
1259  // Track formal parameters
1260  goto_programt snapshot_function_parameters;
1261  for(const auto &param : function_type.parameters())
1262  {
1263  goto_programt payload;
1264  instrument_spec_assigns.track_stack_allocated(
1265  ns.lookup(param.get_identifier()).symbol_expr(), payload);
1266  insert_before_swap_and_advance(function_body, instruction_it, payload);
1267  }
1268 
1269  // Restore internal coherence in the programs
1271 
1272  // Insert write set inclusion checks.
1273  instrument_spec_assigns.instrument_instructions(
1274  function_body, instruction_it, function_body.instructions.end());
1275 }
1276 
1278 {
1279  // Add statements to the source function
1280  // to ensure assigns clause is respected.
1282 
1283  // Rename source function
1284  std::stringstream ss;
1285  ss << CPROVER_PREFIX << "contracts_original_" << function;
1286  const irep_idt mangled(ss.str());
1287  const irep_idt original(function);
1288 
1289  auto old_function = goto_functions.function_map.find(original);
1290  INVARIANT(
1291  old_function != goto_functions.function_map.end(),
1292  "Function to replace must exist in the program.");
1293 
1294  std::swap(goto_functions.function_map[mangled], old_function->second);
1295  goto_functions.function_map.erase(old_function);
1296 
1297  // Place a new symbol with the mangled name into the symbol table
1298  symbolt mangled_sym;
1299  const symbolt *original_sym = symbol_table.lookup(original);
1300  mangled_sym = *original_sym;
1301  mangled_sym.name = mangled;
1302  mangled_sym.base_name = mangled;
1303  mangled_sym.location = original_sym->location;
1304  const auto mangled_found = symbol_table.insert(std::move(mangled_sym));
1305  INVARIANT(
1306  mangled_found.second,
1307  "There should be no existing function called " + ss.str() +
1308  " in the symbol table because that name is a mangled name");
1309 
1310  // Insert wrapper function into goto_functions
1311  auto nexist_old_function = goto_functions.function_map.find(original);
1312  INVARIANT(
1313  nexist_old_function == goto_functions.function_map.end(),
1314  "There should be no function called " + id2string(function) +
1315  " in the function map because that function should have had its"
1316  " name mangled");
1317 
1318  auto mangled_fun = goto_functions.function_map.find(mangled);
1319  INVARIANT(
1320  mangled_fun != goto_functions.function_map.end(),
1321  "There should be a function called " + ss.str() +
1322  " in the function map because we inserted a fresh goto-program"
1323  " with that mangled name");
1324 
1325  goto_functiont &wrapper = goto_functions.function_map[original];
1326  wrapper.parameter_identifiers = mangled_fun->second.parameter_identifiers;
1328  add_contract_check(original, mangled, wrapper.body);
1329 }
1330 
1333  const irep_idt &property_class,
1334  const irep_idt &mode,
1335  goto_programt &dest)
1336 {
1337  source_locationt loc(expr.source_location());
1338  loc.set_property_class(property_class);
1339  std::stringstream comment;
1340  comment << "Assert function pointer '"
1341  << from_expr_using_mode(ns, mode, expr.function_pointer())
1342  << "' obeys contract '"
1343  << from_expr_using_mode(ns, mode, expr.address_of_contract()) << "'";
1344  loc.set_comment(comment.str());
1345  code_assertt assert_expr(
1347  assert_expr.add_source_location() = loc;
1348  goto_programt instructions;
1349  converter.goto_convert(assert_expr, instructions, mode);
1350  dest.destructive_append(instructions);
1351 }
1352 
1355  const irep_idt &mode,
1356  goto_programt &dest)
1357 {
1358  source_locationt loc(expr.source_location());
1359  std::stringstream comment;
1360  comment << "Assume function pointer '"
1361  << from_expr_using_mode(ns, mode, expr.function_pointer())
1362  << "' obeys contract '"
1363  << from_expr_using_mode(ns, mode, expr.address_of_contract()) << "'";
1364  loc.set_comment(comment.str());
1366  expr.function_pointer(), expr.address_of_contract(), loc));
1367 }
1368 
1370  const irep_idt &wrapper_function,
1371  const irep_idt &mangled_function,
1372  goto_programt &dest)
1373 {
1374  PRECONDITION(!dest.instructions.empty());
1375 
1376  const auto &code_type = get_contract(wrapper_function, ns);
1377  auto assigns = code_type.assigns();
1378  auto requires_contract = code_type.requires_contract();
1379  auto ensures_contract = code_type.ensures_contract();
1380  // build:
1381  // decl ret
1382  // decl parameter1 ...
1383  // decl history_parameter1 ... [optional]
1384  // assume(requires) [optional]
1385  // ret=function(parameter1, ...)
1386  // assert(ensures)
1387 
1388  goto_programt check;
1389 
1390  // prepare function call including all declarations
1391  const symbolt &function_symbol = ns.lookup(mangled_function);
1392  code_function_callt call(function_symbol.symbol_expr());
1393 
1394  // Prepare to instantiate expressions in the callee
1395  // with expressions from the call site (e.g. the return value).
1396  exprt::operandst instantiation_values;
1397 
1398  source_locationt source_location = function_symbol.location;
1399  // Set function in source location to original function
1400  source_location.set_function(wrapper_function);
1401 
1402  // decl ret
1403  optionalt<code_returnt> return_stmt;
1404  if(code_type.return_type() != empty_typet())
1405  {
1407  code_type.return_type(),
1408  source_location,
1409  function_symbol.mode,
1410  symbol_table)
1411  .symbol_expr();
1412  check.add(goto_programt::make_decl(r, source_location));
1413 
1414  call.lhs() = r;
1415  return_stmt = code_returnt(r);
1416 
1417  instantiation_values.push_back(r);
1418  }
1419 
1420  // decl parameter1 ...
1421  goto_functionst::function_mapt::iterator f_it =
1422  goto_functions.function_map.find(mangled_function);
1423  PRECONDITION(f_it != goto_functions.function_map.end());
1424 
1425  const goto_functionst::goto_functiont &gf = f_it->second;
1426  for(const auto &parameter : gf.parameter_identifiers)
1427  {
1428  PRECONDITION(!parameter.empty());
1429  const symbolt &parameter_symbol = ns.lookup(parameter);
1431  parameter_symbol.type,
1432  source_location,
1433  parameter_symbol.mode,
1434  symbol_table)
1435  .symbol_expr();
1436  check.add(goto_programt::make_decl(p, source_location));
1438  p, parameter_symbol.symbol_expr(), source_location));
1439 
1440  call.arguments().push_back(p);
1441 
1442  instantiation_values.push_back(p);
1443  }
1444 
1445  is_fresh_enforcet visitor(*this, log, wrapper_function);
1446  visitor.create_declarations();
1447  visitor.add_memory_map_decl(check);
1448  // Generate: assume(requires)
1449  exprt::operandst requires_conjuncts;
1450  for(const auto &r : code_type.requires())
1451  {
1452  requires_conjuncts.push_back(
1453  to_lambda_expr(r).application(instantiation_values));
1454  }
1455  auto requires = conjunction(requires_conjuncts);
1456  requires.add_source_location() =
1457  requires_conjuncts.empty() ? code_type.source_location()
1458  : code_type.requires().front().source_location();
1459  if(!requires.is_false())
1460  {
1461  if(has_subexpr(requires, ID_exists) || has_subexpr(requires, ID_forall))
1462  add_quantified_variable(requires, function_symbol.mode);
1463 
1464  goto_programt assumption;
1466  code_assumet(requires), assumption, function_symbol.mode);
1467  visitor.update_requires(assumption);
1468  check.destructive_append(assumption);
1469  }
1470 
1471  // Prepare the history variables handling
1472  std::pair<goto_programt, goto_programt> ensures_pair;
1473 
1474  // Generate: copies for history variables
1475  exprt::operandst ensures_conjuncts;
1476  for(const auto &r : code_type.ensures())
1477  {
1478  ensures_conjuncts.push_back(
1479  to_lambda_expr(r).application(instantiation_values));
1480  }
1481  auto ensures = conjunction(ensures_conjuncts);
1482  ensures.add_source_location() =
1483  ensures_conjuncts.empty() ? code_type.source_location()
1484  : code_type.ensures().front().source_location();
1485  if(!ensures.is_true())
1486  {
1487  if(has_subexpr(ensures, ID_exists) || has_subexpr(ensures, ID_forall))
1488  add_quantified_variable(ensures, function_symbol.mode);
1489 
1490  // get all the relevant instructions related to history variables
1491  auto assertion = code_assertt(ensures);
1492  assertion.add_source_location() = ensures.source_location();
1493  ensures_pair = create_ensures_instruction(
1494  assertion, ensures.source_location(), function_symbol.mode);
1495  ensures_pair.first.instructions.back()
1496  .source_location_nonconst()
1497  .set_comment("Check ensures clause");
1498  ensures_pair.first.instructions.back()
1499  .source_location_nonconst()
1500  .set_property_class(ID_postcondition);
1501 
1502  // add all the history variable initializations
1503  visitor.update_ensures(ensures_pair.first);
1504  check.destructive_append(ensures_pair.second);
1505  }
1506 
1507  // Translate requires_contract(ptr, contract) clauses to assumptions
1508  for(auto &expr : requires_contract)
1509  {
1512  to_lambda_expr(expr).application(instantiation_values)),
1513  function_symbol.mode,
1514  check);
1515  }
1516 
1517  // ret=mangled_function(parameter1, ...)
1518  check.add(goto_programt::make_function_call(call, source_location));
1519 
1520  // Generate: assert(ensures)
1521  if(ensures.is_not_nil())
1522  {
1523  check.destructive_append(ensures_pair.first);
1524  }
1525 
1526  // Translate ensures_contract(ptr, contract) clauses to assertions
1527  for(auto &expr : ensures_contract)
1528  {
1531  to_lambda_expr(expr).application(instantiation_values)),
1532  ID_postcondition,
1533  function_symbol.mode,
1534  check);
1535  }
1536  if(code_type.return_type() != empty_typet())
1537  {
1539  return_stmt.value().return_value(), source_location));
1540  }
1541 
1542  // kill the is_fresh memory map
1543  visitor.add_memory_map_dead(check);
1544 
1545  // prepend the new code to dest
1546  dest.destructive_insert(dest.instructions.begin(), check);
1547 
1548  // restore global goto_program consistency
1550 }
1551 
1553  const std::set<std::string> &functions) const
1554 {
1555  for(const auto &function : functions)
1556  {
1557  if(
1558  goto_functions.function_map.find(function) ==
1560  {
1562  "Function '" + function + "' was not found in the GOTO program.");
1563  }
1564  }
1565 }
1566 
1567 void code_contractst::replace_calls(const std::set<std::string> &to_replace)
1568 {
1569  if(to_replace.empty())
1570  return;
1571 
1572  log.status() << "Replacing function calls with contracts" << messaget::eom;
1573 
1574  check_all_functions_found(to_replace);
1575 
1576  for(auto &goto_function : goto_functions.function_map)
1577  {
1578  Forall_goto_program_instructions(ins, goto_function.second.body)
1579  {
1580  if(ins->is_function_call())
1581  {
1582  if(ins->call_function().id() != ID_symbol)
1583  continue;
1584 
1585  const irep_idt &called_function =
1586  to_symbol_expr(ins->call_function()).get_identifier();
1587  auto found = std::find(
1588  to_replace.begin(), to_replace.end(), id2string(called_function));
1589  if(found == to_replace.end())
1590  continue;
1591 
1593  goto_function.first,
1594  ins->source_location(),
1595  goto_function.second.body,
1596  ins);
1597  }
1598  }
1599  }
1600 
1601  for(auto &goto_function : goto_functions.function_map)
1602  remove_skip(goto_function.second.body);
1603 
1605 }
1606 
1608  const std::set<std::string> &to_exclude_from_nondet_init)
1609 {
1610  for(auto &goto_function : goto_functions.function_map)
1611  apply_loop_contract(goto_function.first, goto_function.second);
1612 
1613  log.status() << "Adding nondeterministic initialization "
1614  "of static/global variables."
1615  << messaget::eom;
1616  nondet_static(goto_model, to_exclude_from_nondet_init);
1617 }
1618 
1620  const std::set<std::string> &to_enforce,
1621  const std::set<std::string> &to_exclude_from_nondet_init)
1622 {
1623  if(to_enforce.empty())
1624  return;
1625 
1626  log.status() << "Enforcing contracts" << messaget ::eom;
1627 
1628  check_all_functions_found(to_enforce);
1629 
1630  for(const auto &function : to_enforce)
1631  enforce_contract(function);
1632 
1633  log.status() << "Adding nondeterministic initialization "
1634  "of static/global variables."
1635  << messaget::eom;
1636  nondet_static(goto_model, to_exclude_from_nondet_init);
1637 }
Forall_goto_program_instructions
#define Forall_goto_program_instructions(it, program)
Definition: goto_program.h:1234
exception_utils.h
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:36
pointer_offset_size.h
all_dereferences_are_valid
exprt all_dereferences_are_valid(const exprt &expr, const namespacet &ns)
Generate a validity check over all dereferences in an expression.
Definition: utils.cpp:80
goto_functiont::body
goto_programt body
Definition: goto_function.h:26
inlining_decoratort::get_recursive_call_set
const std::set< irep_idt > & get_recursive_call_set() const
Definition: inlining_decorator.h:98
to_code_with_contract_type
const code_with_contract_typet & to_code_with_contract_type(const typet &type)
Cast a typet to a code_with_contract_typet.
Definition: c_types.h:447
format
static format_containert< T > format(const T &o)
Definition: format.h:37
inlining_decoratort::throw_on_recursive_calls
void throw_on_recursive_calls(messaget &log, const int error_code)
Throws the given error code if recursive call warnings happend during inlining.
Definition: inlining_decorator.cpp:81
is_fresh_enforcet
Definition: memory_predicates.h:61
symbol_tablet
The symbol table.
Definition: symbol_table.h:13
to_unary_expr
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition: std_expr.h:361
symbol_table_baset::lookup_ref
const symbolt & lookup_ref(const irep_idt &name) const
Find a symbol in the symbol table for read-only access.
Definition: symbol_table_base.h:104
grapht::size
std::size_t size() const
Definition: graph.h:212
insert_before_swap_and_advance
void insert_before_swap_and_advance(goto_programt &destination, goto_programt::targett &target, goto_programt &payload)
Insert a goto program before a target instruction iterator and advance the iterator.
Definition: utils.cpp:138
has_subexpr
bool has_subexpr(const exprt &expr, const std::function< bool(const exprt &)> &pred)
returns true if the expression has a subexpression that satisfies pred
Definition: expr_util.cpp:139
to_lambda_expr
const lambda_exprt & to_lambda_expr(const exprt &expr)
Cast an exprt to a lambda_exprt.
Definition: mathematical_expr.h:461
source_locationt::as_string
std::string as_string() const
Definition: source_location.h:25
conjunction
exprt conjunction(const exprt::operandst &op)
1) generates a conjunction for two or more operands 2) for one operand, returns the operand 3) return...
Definition: std_expr.cpp:62
source_locationt::set_comment
void set_comment(const irep_idt &comment)
Definition: source_location.h:135
code_contractst::check_apply_loop_contracts
void check_apply_loop_contracts(const irep_idt &function_name, goto_functionst::goto_functiont &goto_function, const local_may_aliast &local_may_alias, goto_programt::targett loop_head, goto_programt::targett loop_end, const loopt &loop, exprt assigns_clause, exprt invariant, exprt decreases_clause, const irep_idt &mode)
Definition: contracts.cpp:51
local_bitvector_analysis.h
goto_programt::make_dead
static instructiont make_dead(const symbol_exprt &symbol, const source_locationt &l=source_locationt::nil())
Definition: goto_program.h:962
code_contractst::enforce_contract
void enforce_contract(const irep_idt &function)
Enforce contract of a single function.
Definition: contracts.cpp:1277
to_history_expr
const history_exprt & to_history_expr(const exprt &expr, const irep_idt &id)
Definition: c_expr.h:219
source_locationt::set_function
void set_function(const irep_idt &function)
Definition: source_location.h:120
nondet_static
static void nondet_static(const namespacet &ns, goto_functionst &goto_functions, const irep_idt &fct_name)
Nondeterministically initializes global scope variables in a goto-function.
Definition: nondet_static.cpp:80
function_cfg_infot
Definition: cfg_info.h:109
code_contractst::check_frame_conditions_function
void check_frame_conditions_function(const irep_idt &function)
Instrument functions to check frame conditions.
Definition: contracts.cpp:1186
goto_inline.h
generate_lexicographic_less_than_check
exprt generate_lexicographic_less_than_check(const std::vector< symbol_exprt > &lhs, const std::vector< symbol_exprt > &rhs)
Generate a lexicographic less-than comparison over ordered tuples.
Definition: utils.cpp:94
goto_programt::make_set_return_value
static instructiont make_set_return_value(exprt return_value, const source_locationt &l=source_locationt::nil())
Definition: goto_program.h:865
fresh_symbol.h
code_contractst::apply_loop_contracts
void apply_loop_contracts(const std::set< std::string > &to_exclude_from_nondet_init={})
Applies loop contract transformations.
Definition: contracts.cpp:1607
code_contractst::add_contract_check
void add_contract_check(const irep_idt &wrapper_function, const irep_idt &mangled_function, goto_programt &dest)
Instruments wrapper_function adding assumptions based on requires clauses and assertions based on ens...
Definition: contracts.cpp:1369
messaget::status
mstreamt & status() const
Definition: message.h:414
code_contractst::replace_calls
void replace_calls(const std::set< std::string > &to_replace)
Replace all calls to each function in the to_replace set with that function's contract.
Definition: contracts.cpp:1567
to_if_expr
const if_exprt & to_if_expr(const exprt &expr)
Cast an exprt to an if_exprt.
Definition: std_expr.h:2403
symbolt::type
typet type
Type of symbol.
Definition: symbol.h:31
remove_skip
void remove_skip(goto_programt &goto_program, goto_programt::targett begin, goto_programt::targett end)
remove unnecessary skip statements
Definition: remove_skip.cpp:87
invalid_input_exceptiont
Thrown when user-provided input cannot be processed.
Definition: exception_utils.h:162
pointer_predicates.h
grapht
A generic directed graph with a parametric node type.
Definition: graph.h:166
cfg_info.h
code_assertt
A non-fatal assertion, which checks a condition then permits execution to continue.
Definition: std_code.h:269
goto_programt::make_end_function
static instructiont make_end_function(const source_locationt &l=source_locationt::nil())
Definition: goto_program.h:992
goto_programt::add
targett add(instructiont &&instruction)
Adds a given instruction at the end.
Definition: goto_program.h:709
grapht::add_node
node_indext add_node(arguments &&... values)
Definition: graph.h:180
exprt
Base class for all expressions.
Definition: expr.h:55
code_contractst::log
messaget & log
Definition: contracts.h:139
havoc_utils.h
symbolt::base_name
irep_idt base_name
Base (non-scoped) name.
Definition: symbol.h:46
code_contractst::assert_function_pointer_obeys_contract
void assert_function_pointer_obeys_contract(const function_pointer_obeys_contract_exprt &expr, const irep_idt &property_class, const irep_idt &mode, goto_programt &dest)
Translates a function_pointer_obeys_contract_exprt into an assertion.
Definition: contracts.cpp:1331
bool_typet
The Boolean type.
Definition: std_types.h:35
messaget::eom
static eomt eom
Definition: message.h:297
instrument_spec_assignst::get_static_locals
void get_static_locals(std::insert_iterator< C > inserter) const
Inserts the detected static local symbols into a target container.
Definition: instrument_spec_assigns.h:465
goto_functionst::function_map
function_mapt function_map
Definition: goto_functions.h:29
symbol_exprt
Expression to hold a symbol (variable)
Definition: std_expr.h:112
goto_programt::make_decl
static instructiont make_decl(const symbol_exprt &symbol, const source_locationt &l=source_locationt::nil())
Definition: goto_program.h:955
nondet_static.h
equal_exprt
Equality.
Definition: std_expr.h:1305
instrument_spec_assignst
A class that generates instrumentation for assigns clause checking.
Definition: instrument_spec_assigns.h:189
code_function_callt::lhs
exprt & lhs()
Definition: goto_instruction_code.h:297
loopt
natural_loops_mutablet::natural_loopt loopt
Definition: loop_utils.h:20
local_may_aliast
Definition: local_may_alias.h:25
code_contractst::apply_function_contract
void apply_function_contract(const irep_idt &function, const source_locationt &location, goto_programt &function_body, goto_programt::targett &target)
Replaces function calls with assertions based on requires clauses, non-deterministic assignments for ...
Definition: contracts.cpp:680
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
goto_programt::make_goto
static instructiont make_goto(targett _target, const source_locationt &l=source_locationt::nil())
Definition: goto_program.h:1030
goto_convertt::goto_convert
void goto_convert(const codet &code, goto_programt &dest, const irep_idt &mode)
Definition: goto_convert.cpp:279
grapht::topsort
std::list< node_indext > topsort() const
Find a topological order of the nodes if graph is DAG, return empty list for non-DAG or empty graph.
Definition: graph.h:879
is_fresh_baset::update_ensures
void update_ensures(goto_programt &ensures)
Definition: memory_predicates.cpp:122
to_binary_expr
const binary_exprt & to_binary_expr(const exprt &expr)
Cast an exprt to a binary_exprt.
Definition: std_expr.h:660
mathematical_types.h
memory_predicates.h
namespacet
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:90
goto_programt::make_function_call
static instructiont make_function_call(const code_function_callt &_code, const source_locationt &l=source_locationt::nil())
Create a function call instruction.
Definition: goto_program.h:1081
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
to_code_type
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition: std_types.h:744
is_fresh_replacet
Definition: memory_predicates.h:76
utils.h
code_contractst::converter
goto_convertt converter
Definition: contracts.h:140
goto_programt::make_assertion
static instructiont make_assertion(const exprt &g, const source_locationt &l=source_locationt::nil())
Definition: goto_program.h:924
symbolt::mode
irep_idt mode
Language mode.
Definition: symbol.h:49
messaget::error
mstreamt & error() const
Definition: message.h:399
find_symbols.h
simplify_gotos
void simplify_gotos(goto_programt &goto_program, namespacet &ns)
Turns goto instructions IF cond GOTO label where the condition statically simplifies to false into SK...
Definition: utils.cpp:162
empty_typet
The empty type.
Definition: std_types.h:50
or_exprt
Boolean OR.
Definition: std_expr.h:2178
goto_programt::destructive_insert
void destructive_insert(const_targett target, goto_programt &p)
Inserts the given program p before target.
Definition: goto_program.h:700
local_may_alias.h
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
havoc_assigns_targetst
A class that further overrides the "safe" havoc utilities, and adds support for havocing pointer_obje...
Definition: utils.h:57
function_pointer_obeys_contract_exprt::function_pointer
const exprt & function_pointer() const
Definition: c_expr.h:357
goto_programt::make_skip
static instructiont make_skip(const source_locationt &l=source_locationt::nil())
Definition: goto_program.h:882
language_util.h
function_pointer_obeys_contract_exprt::address_of_contract
const exprt & address_of_contract() const
Definition: c_expr.h:377
c_expr.h
PRECONDITION
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
code_contractst::add_quantified_variable
void add_quantified_variable(exprt &expression, const irep_idt &mode)
This function recursively searches expression to find nested or non-nested quantified expressions.
Definition: contracts.cpp:489
symbol_exprt::get_identifier
const irep_idt & get_identifier() const
Definition: std_expr.h:142
boolean_negate
exprt boolean_negate(const exprt &src)
negate a Boolean expression, possibly removing a not_exprt, and swapping false and true
Definition: expr_util.cpp:127
code_assumet
An assumption, which must hold in subsequent code.
Definition: std_code.h:216
add_pragma_disable_assigns_check
void add_pragma_disable_assigns_check(source_locationt &location)
Adds a pragma on a source_locationt to disable inclusion checking.
Definition: instrument_spec_assigns.cpp:70
symbolt::symbol_expr
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
Definition: symbol.cpp:121
havoc_assigns_clause_targetst
Class to generate havocking instructions for target expressions of a function contract's assign claus...
Definition: havoc_assigns_clause_targets.h:44
code_contractst::assume_function_pointer_obeys_contract
void assume_function_pointer_obeys_contract(const function_pointer_obeys_contract_exprt &expr, const irep_idt &mode, goto_programt &dest)
Translates a function_pointer_obeys_contract_exprt into an assignment.
Definition: contracts.cpp:1353
loop_templatet
A loop, specified as a set of instructions.
Definition: loop_analysis.h:23
symbol_tablet::insert
virtual std::pair< symbolt &, bool > insert(symbolt symbol) override
Author: Diffblue Ltd.
Definition: symbol_table.cpp:17
havoc_utilst::append_full_havoc_code
void append_full_havoc_code(const source_locationt location, goto_programt &dest) const
Append goto instructions to havoc the full assigns set.
Definition: havoc_utils.cpp:21
code_contractst::apply_loop_contract
void apply_loop_contract(const irep_idt &function, goto_functionst::goto_functiont &goto_function)
Apply loop contracts, whenever available, to all loops in function.
Definition: contracts.cpp:929
to_symbol_expr
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:222
code_typet
Base type of functions.
Definition: std_types.h:538
code_contractst::goto_model
goto_modelt & goto_model
Definition: contracts.h:135
irept::is_nil
bool is_nil() const
Definition: irep.h:376
irept::id
const irep_idt & id() const
Definition: irep.h:396
goto_functiont
A goto function, consisting of function body (see body) and parameter identifiers (see parameter_iden...
Definition: goto_function.h:23
exprt::operandst
std::vector< exprt > operandst
Definition: expr.h:58
is_fresh_baset::add_memory_map_dead
void add_memory_map_dead(goto_programt &program)
Definition: memory_predicates.cpp:156
assignst
std::set< exprt > assignst
Definition: havoc_utils.h:23
code_contractst::ns
namespacet ns
Definition: contracts.h:132
false_exprt
The Boolean constant false.
Definition: std_expr.h:3016
loop_cfg_infot
Definition: cfg_info.h:141
goto_function_inline
void goto_function_inline(goto_modelt &goto_model, const irep_idt function, message_handlert &message_handler, bool adjust_function, bool caching)
Transitively inline all function calls made from a particular function.
Definition: goto_inline.cpp:239
code_typet::parameters
const parameterst & parameters() const
Definition: std_types.h:655
natural_loops_templatet< goto_programt, goto_programt::targett >
grapht::add_edge
void add_edge(node_indext a, node_indext b)
Definition: graph.h:232
std_code.h
code_function_callt::arguments
argumentst & arguments()
Definition: goto_instruction_code.h:317
optionalt
nonstd::optional< T > optionalt
Definition: optional.h:35
function_pointer_obeys_contract_exprt
A class for expressions representing a requires_contract(fptr, contract) clause or an ensures_contrac...
Definition: c_expr.h:327
inlining_decoratort
Decorator for a message_handlert used during function inlining that collect names of GOTO functions c...
Definition: inlining_decorator.h:42
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
goto_program.h
source_locationt
Definition: source_location.h:18
side_effect_expr_nondett
A side_effect_exprt that returns a non-deterministically chosen value.
Definition: std_code.h:1519
goto_functionst::goto_functiont
::goto_functiont goto_functiont
Definition: goto_functions.h:27
code_contractst::check_all_functions_found
void check_all_functions_found(const std::set< std::string > &functions) const
Throws an exception if some function functions is found in the program.
Definition: contracts.cpp:1552
goto_programt::instructions
instructionst instructions
The list of instructions in the goto program.
Definition: goto_program.h:592
instrument_spec_assignst::track_static_locals_between
void track_static_locals_between(goto_programt::const_targett it, const goto_programt::const_targett end, goto_programt &dest)
Searches the goto instructions reachable between the given it and end target instructions to identify...
Definition: instrument_spec_assigns.cpp:183
expr_util.h
Deprecated expression utility functions.
contracts.h
goto_functionst
A collection of goto functions.
Definition: goto_functions.h:24
code_with_contract_typet
Definition: c_types.h:357
get_contract
static const code_with_contract_typet & get_contract(const irep_idt &function, const namespacet &ns)
Definition: contracts.cpp:658
messaget::get_message_handler
message_handlert & get_message_handler()
Definition: message.h:184
is_loop_free
bool is_loop_free(const goto_programt &goto_program, namespacet &ns, messaget &log)
Returns true iff the given program is loop-free, i.e.
Definition: utils.cpp:173
format_expr.h
instrument_spec_assignst::track_static_locals
void track_static_locals(goto_programt &dest)
Searches the goto instructions reachable from the start to the end of the instrumented function's ins...
Definition: instrument_spec_assigns.cpp:155
code_contractst::create_ensures_instruction
std::pair< goto_programt, goto_programt > create_ensures_instruction(codet &expression, source_locationt location, const irep_idt &mode)
This function creates and returns an instruction that corresponds to the ensures clause.
Definition: contracts.cpp:635
graph.h
code_returnt
goto_instruction_codet representation of a "return from a function" statement.
Definition: goto_instruction_code.h:494
code_contractst::goto_functions
goto_functionst & goto_functions
Definition: contracts.h:137
graph_nodet
This class represents a node in a directed graph.
Definition: graph.h:34
to_quantifier_expr
const quantifier_exprt & to_quantifier_expr(const exprt &expr)
Cast an exprt to a quantifier_exprt.
Definition: mathematical_expr.h:319
symbolt::location
source_locationt location
Source code location of definition of symbol.
Definition: symbol.h:37
symbolt
Symbol table entry.
Definition: symbol.h:27
instrument_spec_assigns.h
havoc_assigns_clause_targets.h
grapht::get_predecessors
std::vector< node_indext > get_predecessors(const node_indext &n) const
Definition: graph.h:943
instrument_spec_assignst::instrument_instructions
void instrument_instructions(goto_programt &body, goto_programt::targett instruction_it, const goto_programt::targett &instruction_end, const std::function< bool(const goto_programt::targett &)> &pred={})
Instruments a sequence of instructions with inclusion checks.
Definition: instrument_spec_assigns.cpp:322
code_contractst::get_symbol_table
symbol_tablet & get_symbol_table()
Definition: contracts.cpp:1176
messaget::conditional_output
void conditional_output(mstreamt &mstream, const std::function< void(mstreamt &)> &output_generator) const
Generate output to message_stream using output_generator if the configured verbosity is at least as h...
Definition: message.cpp:139
CPROVER_PREFIX
#define CPROVER_PREFIX
Definition: cprover_prefix.h:14
goto_functionst::update
void update()
Definition: goto_functions.h:83
goto_programt
A generic container class for the GOTO intermediate representation of one function.
Definition: goto_program.h:72
code_contractst::summarized
std::unordered_set< irep_idt > summarized
Definition: contracts.h:142
code_contractst::replace_history_parameter
void replace_history_parameter(exprt &expr, std::map< exprt, exprt > &parameter2history, source_locationt location, const irep_idt &mode, goto_programt &history, const irep_idt &id)
This function recursively identifies the "old" expressions within expr and replaces them with corresp...
Definition: contracts.cpp:560
symbol_table_baset::lookup
const symbolt * lookup(const irep_idt &name) const
Find a symbol in the symbol table for read-only access.
Definition: symbol_table_base.h:95
code_typet::return_type
const typet & return_type() const
Definition: std_types.h:645
goto_functiont::parameter_identifiers
parameter_identifierst parameter_identifiers
The identifiers of the parameters of this function.
Definition: goto_function.h:33
messaget::mstreamt
Definition: message.h:223
instrument_spec_assignst::track_spec_target
void track_spec_target(const exprt &expr, goto_programt &dest)
Track an assigns clause target and generate snaphsot instructions and well-definedness assertions in ...
Definition: instrument_spec_assigns.cpp:89
new_tmp_symbol
const symbolt & new_tmp_symbol(const typet &type, const source_locationt &location, const irep_idt &mode, symbol_table_baset &symtab, std::string suffix, bool is_auxiliary)
Adds a fresh and uniquely named symbol to the symbol table.
Definition: utils.cpp:148
exprt::operands
operandst & operands()
Definition: expr.h:94
loop_cfg_infot::erase_locals
void erase_locals(std::set< exprt > &exprs)
Definition: cfg_info.h:170
r
static int8_t r
Definition: irep_hash.h:60
is_fresh_enforcet::create_declarations
virtual void create_declarations()
Definition: memory_predicates.cpp:275
messaget::debug
mstreamt & debug() const
Definition: message.h:429
exprt::add_source_location
source_locationt & add_source_location()
Definition: expr.h:216
goto_programt::insert_before_swap
void insert_before_swap(targett target)
Insertion that preserves jumps to "target".
Definition: goto_program.h:613
is_fresh_replacet::create_declarations
virtual void create_declarations()
Definition: memory_predicates.cpp:354
code_contractst::enforce_contracts
void enforce_contracts(const std::set< std::string > &to_enforce, const std::set< std::string > &to_exclude_from_nondet_init={})
Turn requires & ensures into assumptions and assertions for each of the named functions.
Definition: contracts.cpp:1619
inlining_decorator.h
remove_skip.h
code_assignt
A goto_instruction_codet representing an assignment in the program.
Definition: goto_instruction_code.h:22
message.h
true_exprt
The Boolean constant true.
Definition: std_expr.h:3007
code_contractst::get_goto_functions
goto_functionst & get_goto_functions()
Definition: contracts.cpp:1181
messaget::warning
mstreamt & warning() const
Definition: message.h:404
comment
static std::string comment(const rw_set_baset::entryt &entry, bool write)
Definition: race_check.cpp:109
to_multi_ary_expr
const multi_ary_exprt & to_multi_ary_expr(const exprt &expr)
Cast an exprt to a multi_ary_exprt.
Definition: std_expr.h:932
goto_programt::instructiont
This class represents an instruction in the GOTO intermediate representation.
Definition: goto_program.h:180
history_exprt::expression
const exprt & expression() const
Definition: c_expr.h:212
exprt::source_location
const source_locationt & source_location() const
Definition: expr.h:211
c_types.h
get_fresh_aux_symbol
symbolt & get_fresh_aux_symbol(const typet &type, const std::string &name_prefix, const std::string &basename_prefix, const source_locationt &source_location, const irep_idt &symbol_mode, const namespacet &ns, symbol_table_baset &symbol_table)
Installs a fresh-named symbol with respect to the given namespace ns with the requested name pattern ...
Definition: fresh_symbol.cpp:32
instrument_spec_assignst::track_stack_allocated
void track_stack_allocated(const symbol_exprt &symbol_expr, goto_programt &dest)
Track a stack-allocated object and generate snaphsot instructions in dest.
Definition: instrument_spec_assigns.cpp:99
symbolt::name
irep_idt name
The unique identifier.
Definition: symbol.h:40
goto_programt::targett
instructionst::iterator targett
Definition: goto_program.h:586
from_expr_using_mode
std::string from_expr_using_mode(const namespacet &ns, const irep_idt &mode, const exprt &expr)
Formats an expression using the given namespace, using the given mode to retrieve the language printe...
Definition: language_util.cpp:21
code_contractst::symbol_table
symbol_tablet & symbol_table
Definition: contracts.h:136
loop_analysist::loop_map
loop_mapt loop_map
Definition: loop_analysis.h:88
validation_modet::INVARIANT
@ INVARIANT
is_fresh_baset::update_requires
void update_requires(goto_programt &requires)
Definition: memory_predicates.cpp:112
get_assigns
void get_assigns(const local_may_aliast &local_may_alias, const loopt &loop, assignst &assigns)
Definition: loop_utils.cpp:72
analysis_exceptiont
Thrown when an unexpected error occurs during the analysis (e.g., when the SAT solver returns an erro...
Definition: exception_utils.h:153
source_locationt::set_property_class
void set_property_class(const irep_idt &property_class)
Definition: source_location.h:130
mathematical_expr.h
codet
Data structure for representing an arbitrary statement in a program.
Definition: std_code_base.h:28
not_exprt
Boolean negation.
Definition: std_expr.h:2277
is_fresh_baset::add_memory_map_decl
void add_memory_map_decl(goto_programt &program)
Definition: memory_predicates.cpp:143
to_function_pointer_obeys_contract_expr
const function_pointer_obeys_contract_exprt & to_function_pointer_obeys_contract_expr(const exprt &expr)
Cast an exprt to a function_pointer_obeys_contract_exprt.
Definition: c_expr.h:407