49 exprt decreases_clause,
52 const auto loop_head_location = loop_head->source_location();
53 const auto loop_number = loop_end->loop_number;
56 const auto &decreases_clause_exprs = decreases_clause.
operands();
60 std::vector<symbol_exprt> old_decreases_vars, new_decreases_vars;
119 invariant.
swap(replace_history_result.expression_after_replacement);
120 const auto &history_var_map = replace_history_result.parameter_to_history;
124 replace_history_result.history_construction;
128 const auto entered_loop =
131 id2string(loop_head_location.get_function()),
132 std::string(
ENTERED_LOOP) +
"__" + std::to_string(loop_number),
137 pre_loop_head_instrs.
add(
139 pre_loop_head_instrs.
add(
144 const auto initial_invariant_val =
147 id2string(loop_head_location.get_function()),
153 pre_loop_head_instrs.
add(
160 initial_invariant_val, invariant};
166 initial_invariant_value_assignment, pre_loop_head_instrs, mode);
173 id2string(loop_head_location.get_function()),
179 pre_loop_head_instrs.
add(
181 pre_loop_head_instrs.
add(
195 log.get_message_handler());
198 loop_head, loop_end, snapshot_instructions);
203 if(assigns_clause.
is_nil())
219 log.debug() <<
"No loop assigns clause provided. Inferred targets: {";
221 bool ran_once =
false;
222 for(
const auto &target : to_havoc)
229 target, snapshot_instructions);
234 std::inserter(to_havoc, to_havoc.end()));
238 log.error() <<
"Failed to infer variables being modified by the loop at "
239 << loop_head_location
240 <<
".\nPlease specify an assigns clause.\nReason:"
249 for(
const auto &target : assigns_clause.
operands())
251 to_havoc.insert(target);
264 pre_loop_head_instrs.
add(
271 const auto step_case_target =
284 "Check loop invariant before entry");
287 converter.
goto_convert(assertion, pre_loop_head_instrs, mode);
294 goto_function.body.destructive_insert(
301 const auto in_loop_havoc_block =
304 id2string(loop_head_location.get_function()),
310 pre_loop_head_instrs.
add(
312 pre_loop_head_instrs.
add(
317 pre_loop_head_instrs.
add(
324 goto_function.body.destructive_insert(loop_head, pre_loop_head_instrs);
334 converter.
goto_convert(assumption, pre_loop_head_instrs, mode);
339 for(
const auto &clause : decreases_clause.
operands())
341 const auto old_decreases_var =
344 id2string(loop_head_location.get_function()),
350 pre_loop_head_instrs.
add(
352 old_decreases_vars.push_back(old_decreases_var);
354 const auto new_decreases_var =
357 id2string(loop_head_location.get_function()),
363 pre_loop_head_instrs.
add(
365 new_decreases_vars.push_back(new_decreases_var);
369 if(loop_end->is_goto() && loop_end->condition() !=
true)
371 log.error() <<
"Loop contracts are unsupported on do/while loops: "
382 if(!decreases_clause.
is_nil())
384 for(
size_t i = 0; i < old_decreases_vars.size(); i++)
387 old_decreases_vars[i], decreases_clause_exprs[i]};
392 old_decreases_assignment, pre_loop_head_instrs, mode);
395 goto_function.body.destructive_insert(
403 goto_function.body.destructive_insert(
418 pre_loop_end_instrs.
add(
424 step_case_target, in_base_case, loop_head_location));
438 "Check that loop invariant is preserved");
441 converter.
goto_convert(assertion, pre_loop_end_instrs, mode);
446 if(!decreases_clause.
is_nil())
448 for(
size_t i = 0; i < new_decreases_vars.size(); i++)
451 new_decreases_vars[i], decreases_clause_exprs[i]};
456 new_decreases_assignment, pre_loop_end_instrs, mode);
463 new_decreases_vars, old_decreases_vars)};
466 "Check decreases clause on loop iteration");
470 monotonic_decreasing_assertion, pre_loop_end_instrs, mode);
473 for(
size_t i = 0; i < old_decreases_vars.size(); i++)
475 pre_loop_end_instrs.
add(
477 pre_loop_end_instrs.
add(
488 loop_end->turn_into_assume();
489 loop_end->condition_nonconst() =
boolean_negate(loop_end->condition());
491 std::set<goto_programt::targett, goto_programt::target_less_than>
495 for(
const auto &t : loop)
500 auto exit_target = t->get_target();
502 loop.contains(exit_target) ||
503 seen_targets.find(exit_target) != seen_targets.end())
506 seen_targets.insert(exit_target);
512 "Check that loop instrumentation was not truncated");
515 annotated_location));
517 pre_loop_exit_instrs.
add(
519 pre_loop_exit_instrs.
add(
521 for(
const auto &v : history_var_map)
523 pre_loop_exit_instrs.
add(
528 goto_function.body, exit_target, pre_loop_exit_instrs);
539 it.is_function_call() && it.call_function().id() == ID_symbol &&
545 it.source_location());
555 exprt &instantiated_clause,
574 is_fresh_update(constraint);
582 const std::string &function_str =
id2string(function);
583 const auto &function_symbol = ns.
lookup(function);
586 if(ns.
lookup(
"contract::" + function_str, contract_sym))
594 type == function_symbol.type,
595 "front-end should have rejected re-declarations with a different type");
606 const auto &const_target =
610 PRECONDITION(const_target->call_function().id() == ID_symbol);
614 const symbolt &function_symbol =
ns.lookup(target_function);
620 if(
ns.lookup(
"contract::" +
id2string(target_function), contract_sym))
623 "Function '" +
id2string(target_function) +
624 "' does not have a contract. " +
625 "A contract must be explicitly provided. If you need a trivial " +
626 "contract, please add explicit " +
628 "ensures clauses to the function.");
639 std::optional<exprt> call_ret_opt = {};
642 bool call_ret_is_fresh_var =
false;
647 if(target->call_lhs().is_not_nil())
653 auto &lhs_expr = const_target->call_lhs();
654 call_ret_opt = lhs_expr;
655 instantiation_values.push_back(lhs_expr);
662 type.c_ensures().begin(),
663 type.c_ensures().end(),
665 return has_symbol_expr(
666 to_lambda_expr(e).where(), CPROVER_PREFIX
"return_value", true);
671 call_ret_is_fresh_var =
true;
675 "ignored_return_value",
676 const_target->source_location(),
681 call_ret_opt = fresh_sym_expr;
682 instantiation_values.push_back(fresh_sym_expr);
687 instantiation_values.push_back(
694 const auto &arguments = const_target->call_arguments();
695 instantiation_values.insert(
696 instantiation_values.end(), arguments.begin(), arguments.end());
698 const auto &mode = function_symbol.
mode;
709 for(
const auto &clause : type.c_requires())
711 auto instantiated_clause =
715 _location.
set_comment(std::string(
"Check requires clause of ")
716 .append(target_function.
c_str())
718 .append(function.
c_str()));
735 for(
auto clause : type.c_ensures())
737 auto instantiated_clause =
742 instantiated_ensures_clauses.push_back(instantiated_clause);
748 for(
auto &target : type.c_assigns())
749 targets.push_back(
to_lambda_expr(target).application(instantiation_values));
763 log.get_message_handler());
765 havocker.get_instructions(havoc_instructions);
768 if(call_ret_opt.has_value())
770 auto &call_ret = call_ret_opt.value();
771 auto &loc = call_ret.source_location();
772 auto &type = call_ret.type();
775 if(call_ret_is_fresh_var)
776 havoc_instructions.
add(
788 for(
auto &clause : instantiated_ensures_clauses)
793 std::string(
"Attempt to assume false at ")
794 .append(clause.source_location().as_string())
795 .append(
".\nPlease update ensures clause to avoid vacuity."));
813 if(call_ret_is_fresh_var)
815 log.conditional_output(
817 target->output(mstream);
818 mstream << messaget::eom;
845 const bool may_have_loops = std::any_of(
846 goto_function.body.instructions.begin(),
847 goto_function.body.instructions.end(),
849 return instruction.is_backwards_goto();
876 struct loop_graph_nodet :
public graph_nodet<empty_edget>
880 exprt assigns_clause, invariant, decreases_clause;
886 const exprt &assigns,
888 const exprt &decreases)
892 assigns_clause(assigns),
894 decreases_clause(decreases)
900 std::list<size_t> to_check_contracts_on_children;
904 std::pair<goto_programt::targett, natural_loops_mutablet::loopt>,
908 for(
const auto &loop_head_and_content : natural_loops.
loop_map)
910 const auto &loop_body = loop_head_and_content.second;
912 if(loop_body.size() <= 1)
915 auto loop_head = loop_head_and_content.first;
916 auto loop_end = loop_head;
919 for(
const auto &t : loop_body)
922 t->is_goto() && t->get_target() == loop_head &&
923 t->location_number > loop_end->location_number)
927 if(loop_end == loop_head)
929 log.error() <<
"Could not find end of the loop starting at: "
942 for(
const auto &i : loop_body)
945 loop_head->location_number > i->location_number ||
946 i->location_number > loop_end->location_number)
948 log.conditional_output(
950 mstream <<
"Computed loop at " << loop_head->source_location()
951 <<
"contains an instruction beyond [loop_head, loop_end]:"
954 mstream << messaget::eom;
960 if(!loop_head_ends.emplace(loop_head, std::make_pair(loop_end, loop_body))
965 for(
auto &loop_head_end : loop_head_ends)
967 auto loop_head = loop_head_end.first;
968 auto loop_end = loop_head_end.second.first;
978 loop_end->set_target(loop_head);
983 exprt decreases_clause =
993 <<
"The loop at " << loop_head->source_location().as_string()
994 <<
" does not have an invariant in its contract.\n"
995 <<
"Hence, a default invariant ('true') is being used.\n"
996 <<
"This choice is sound, but verification may fail"
997 <<
" if it is be too weak to prove the desired properties."
1004 if(decreases_clause.
is_nil())
1006 log.warning() <<
"The loop at "
1007 << loop_head->source_location().as_string()
1008 <<
" does not have a decreases clause in its contract.\n"
1009 <<
"Termination of this loop will not be verified."
1014 const auto idx = loop_nesting_graph.
add_node(
1015 loop_head_end.second.second,
1024 decreases_clause.
is_nil())
1027 to_check_contracts_on_children.push_back(idx);
1030 for(
size_t outer = 0; outer < loop_nesting_graph.
size(); ++outer)
1032 for(
size_t inner = 0; inner < loop_nesting_graph.
size(); ++inner)
1037 if(loop_nesting_graph[outer].content.contains(
1038 loop_nesting_graph[inner].head_target))
1040 if(!loop_nesting_graph[outer].content.contains(
1041 loop_nesting_graph[inner].end_target))
1044 <<
"Overlapping loops at:\n"
1045 << loop_nesting_graph[outer].head_target->source_location()
1047 << loop_nesting_graph[inner].head_target->source_location()
1048 <<
"\nLoops must be nested or sequential for contracts to be "
1052 loop_nesting_graph.
add_edge(inner, outer);
1058 while(!to_check_contracts_on_children.empty())
1060 const auto loop_idx = to_check_contracts_on_children.front();
1061 to_check_contracts_on_children.pop_front();
1063 const auto &loop_node = loop_nesting_graph[loop_idx];
1065 loop_node.assigns_clause.is_nil() && loop_node.invariant.is_nil() &&
1066 loop_node.decreases_clause.is_nil())
1069 <<
"Inner loop at: " << loop_node.head_target->source_location()
1070 <<
" does not have contracts, but an enclosing loop does.\n"
1071 <<
"Please provide contracts for this loop, or unwind it first."
1077 to_check_contracts_on_children.push_back(child_idx);
1082 for(
const auto &idx : loop_nesting_graph.
topsort())
1084 const auto &loop_node = loop_nesting_graph[idx];
1086 loop_node.assigns_clause.is_nil() && loop_node.invariant.is_nil() &&
1087 loop_node.decreases_clause.is_nil())
1106 std::to_string(loop_node.end_target->loop_number) +
1114 loop_node.head_target,
1115 loop_node.end_target,
1116 updated_loops.
loop_map[loop_node.head_target],
1117 loop_node.assigns_clause,
1118 loop_node.invariant,
1119 loop_node.decreases_clause,
1131 "Function '" +
id2string(function) +
"'must exist in the goto program");
1133 const auto &goto_function = function_obj->second;
1134 auto &function_body = function_obj->second.body;
1143 log.get_message_handler());
1166 "Loops remain in function '" +
id2string(function) +
1167 "', assigns clause checking instrumentation cannot be applied.");
1170 auto instruction_it = function_body.instructions.begin();
1174 function_body, instruction_it, snapshot_static_locals);
1177 const symbolt &function_symbol =
ns.lookup(function);
1183 instantiation_values.push_back(
exprt{ID_nil, function_type.
return_type()});
1184 for(
const auto ¶m : function_type.
parameters())
1186 instantiation_values.push_back(
1187 ns.lookup(param.get_identifier()).symbol_expr());
1193 to_lambda_expr(target).application(instantiation_values), payload);
1199 for(
const auto ¶m : function_type.
parameters())
1203 ns.lookup(param.get_identifier()).symbol_expr(), payload);
1212 function_body, instruction_it, function_body.instructions.end());
1222 std::stringstream ss;
1230 "Function to replace must exist in the program.");
1232 std::swap(
goto_functions.function_map[mangled], old_function->second);
1237 sl.
set_file(
"instrumented for code contracts");
1240 symbolt mangled_sym = *original_sym;
1241 mangled_sym.
name = mangled;
1244 const auto mangled_found =
symbol_table.insert(std::move(mangled_sym));
1246 mangled_found.second,
1247 "There should be no existing function called " + ss.str() +
1248 " in the symbol table because that name is a mangled name");
1251 auto nexist_old_function =
goto_functions.function_map.find(original);
1254 "There should be no function called " +
id2string(function) +
1255 " in the function map because that function should have had its"
1261 "There should be a function called " + ss.str() +
1262 " in the function map because we inserted a fresh goto-program"
1263 " with that mangled name");
1290 const symbolt &function_symbol =
ns.lookup(mangled_function);
1302 std::optional<code_returnt> return_stmt;
1306 code_type.return_type(),
1310 function_symbol.
mode,
1318 instantiation_values.push_back(
r);
1322 goto_functionst::function_mapt::iterator f_it =
1327 for(
const auto ¶meter : gf.parameter_identifiers)
1330 const symbolt ¶meter_symbol =
ns.lookup(parameter);
1332 parameter_symbol.
type,
1336 parameter_symbol.
mode,
1341 p, parameter_symbol.
symbol_expr(), source_location));
1345 instantiation_values.push_back(p);
1354 for(
const auto &clause : code_type.c_requires())
1356 auto instantiated_clause =
1358 if(instantiated_clause ==
false)
1361 std::string(
"Attempt to assume false at ")
1362 .append(clause.source_location().as_string())
1363 .append(
".\nPlease update requires clause to avoid vacuity."));
1372 instantiated_clause,
1373 function_symbol.
mode,
1375 visitor.update_requires(c_requires);
1383 for(
auto clause : code_type.c_ensures())
1385 auto instantiated_clause =
1390 instantiated_ensures_clauses.push_back(instantiated_clause);
1397 for(
auto &clause : instantiated_ensures_clauses)
1407 function_symbol.
mode,
1408 [&visitor](
goto_programt &ensures) { visitor.update_ensures(ensures); },
1416 return_stmt.value().return_value(), source_location));
1430 const std::set<std::string> &functions)
const
1432 for(
const auto &function : functions)
1439 "Function '" + function +
"' was not found in the GOTO program.");
1446 if(to_replace.empty())
1449 log.status() <<
"Replacing function calls with contracts" <<
messaget::eom;
1457 if(ins->is_function_call())
1459 if(ins->call_function().id() != ID_symbol)
1464 auto found = std::find(
1465 to_replace.begin(), to_replace.end(),
id2string(called_function));
1466 if(found == to_replace.end())
1470 goto_function.first,
1471 ins->source_location(),
1472 goto_function.second.body,
1485 const std::set<std::string> &to_exclude_from_nondet_init)
1490 log.status() <<
"Adding nondeterministic initialization "
1491 "of static/global variables."
1510 auto &goto_function = goto_function_entry.second;
1511 bool is_in_loop_havoc_block =
false;
1513 unsigned loop_number_of_loop_havoc = 0;
1515 goto_function.body.instructions.begin();
1516 it_instr != goto_function.body.instructions.end();
1529 const auto &assign_lhs =
1532 id2string(assign_lhs->get_identifier()),
1545 is_in_loop_havoc_block = it_instr->assign_rhs() ==
true_exprt();
1546 const auto &assign_lhs =
1549 id2string(assign_lhs->get_identifier()),
1555 if(is_in_loop_havoc_block && it_instr->is_assign())
1567 const std::set<std::string> &to_enforce,
1568 const std::set<std::string> &to_exclude_from_nondet_init)
1570 if(to_enforce.empty())
1573 log.status() <<
"Enforcing contracts" << messaget ::eom;
1577 for(
const auto &function : to_enforce)
1580 log.status() <<
"Adding nondeterministic initialization "
1581 "of static/global variables."
const code_with_contract_typet & to_code_with_contract_type(const typet &type)
Cast a typet to a code_with_contract_typet.
Classes providing CFG-based information about symbols to guide simplifications in function and loop a...
Thrown when an unexpected error occurs during the analysis (e.g., when the SAT solver returns an erro...
A non-fatal assertion, which checks a condition then permits execution to continue.
A goto_instruction_codet representing an assignment in the program.
An assumption, which must hold in subsequent code.
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 ...
void enforce_contract(const irep_idt &function)
Enforce contract of a single function.
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)
void apply_loop_contract(const irep_idt &function, goto_functionst::goto_functiont &goto_function)
Apply loop contracts, whenever available, to all loops in function.
void check_all_functions_found(const std::set< std::string > &functions) const
Throws an exception if some function functions is found in the program.
void check_frame_conditions_function(const irep_idt &function)
Instrument functions to check frame conditions.
void apply_loop_contracts(const std::set< std::string > &to_exclude_from_nondet_init={})
Applies loop contract transformations.
symbol_tablet & symbol_table
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.
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.
std::unordered_set< irep_idt > summarized
std::unordered_set< goto_programt::const_targett, const_target_hash > loop_havoc_set
Loop havoc instructions instrumented during applying loop contracts.
loop_contract_configt loop_contract_config
std::list< std::string > loop_names
Name of loops we are going to unwind.
goto_functionst & goto_functions
std::unordered_map< goto_programt::const_targett, unsigned, const_target_hash > original_loop_number_map
Store the map from instrumented instructions for loop contracts to their original loop numbers.
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...
goto_instruction_codet representation of a function call statement.
goto_instruction_codet representation of a "return from afunction" statement.
const parameterst & parameters() const
const typet & return_type() const
const char * c_str() const
Base class for all expressions.
std::vector< exprt > operandst
source_locationt & add_source_location()
The Boolean constant false.
void goto_convert(const codet &code, goto_programt &dest, const irep_idt &mode)
::goto_functiont goto_functiont
A goto function, consisting of function body (see body) and parameter identifiers (see parameter_iden...
parameter_identifierst parameter_identifiers
The identifiers of the parameters of this function.
This class represents an instruction in the GOTO intermediate representation.
A generic container class for the GOTO intermediate representation of one function.
instructionst instructions
The list of instructions in the goto program.
static instructiont make_set_return_value(exprt return_value, const source_locationt &l=source_locationt::nil())
static instructiont make_dead(const symbol_exprt &symbol, const source_locationt &l=source_locationt::nil())
void insert_before_swap(targett target)
Insertion that preserves jumps to "target".
void destructive_insert(const_targett target, goto_programt &p)
Inserts the given program p before target.
static instructiont make_end_function(const source_locationt &l=source_locationt::nil())
instructionst::iterator targett
instructionst::const_iterator const_targett
void destructive_append(goto_programt &p)
Appends the given program p to *this. p is destroyed.
static instructiont make_assignment(const code_assignt &_code, const source_locationt &l=source_locationt::nil())
Create an assignment instruction.
static instructiont make_skip(const source_locationt &l=source_locationt::nil())
static instructiont make_function_call(const code_function_callt &_code, const source_locationt &l=source_locationt::nil())
Create a function call instruction.
instructiont::target_less_than target_less_than
targett add(instructiont &&instruction)
Adds a given instruction at the end.
static instructiont make_goto(targett _target, const source_locationt &l=source_locationt::nil())
static instructiont make_decl(const symbol_exprt &symbol, const source_locationt &l=source_locationt::nil())
static instructiont make_assertion(const exprt &g, const source_locationt &l=source_locationt::nil())
This class represents a node in a directed graph.
A generic directed graph with a parametric node type.
std::vector< node_indext > get_predecessors(const node_indext &n) const
node_indext add_node(arguments &&... values)
void add_edge(node_indext a, node_indext b)
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.
Class to generate havocking instructions for target expressions of a function contract's assign claus...
A class that further overrides the "safe" havoc utilities, and adds support for havocing pointer_obje...
void append_full_havoc_code(const source_locationt location, goto_programt &dest)
Append goto instructions to havoc the full assigns set.
Decorator for a message_handlert used during function inlining that collect names of GOTO functions c...
void throw_on_recursive_calls(messaget &log, const int error_code)
Throws the given error code if recursive call warnings happend during inlining.
A class that generates instrumentation for assigns clause checking.
void track_spec_target(const exprt &expr, goto_programt &dest)
Track an assigns clause target and generate snaphsot instructions and well-definedness assertions in ...
void track_stack_allocated(const symbol_exprt &symbol_expr, goto_programt &dest)
Track a stack-allocated object and generate snaphsot instructions in dest.
void track_static_locals(goto_programt &dest)
Searches the goto instructions reachable from the start to the end of the instrumented function's ins...
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.
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...
void get_static_locals(std::insert_iterator< C > inserter) const
Inserts the detected static local symbols into a target container.
Thrown when we can't handle something in an input source file.
void add_memory_map_decl(goto_programt &program)
void update_requires(goto_programt &requires_)
void add_memory_map_dead(goto_programt &program)
void update_ensures(goto_programt &ensures)
virtual void create_declarations()
virtual void create_declarations()
exprt application(const operandst &arguments) const
loop_templatet< T, C > loopt
void erase_locals(std::set< exprt > &exprs)
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Boolean OR All operands must be boolean, and the result is always boolean.
A side_effect_exprt that returns a non-deterministically chosen value.
void set_comment(const irep_idt &comment)
void set_property_class(const irep_idt &property_class)
const irep_idt & get_function() const
const irep_idt & get_line() const
const irep_idt & get_property_class() const
void set_file(const irep_idt &file)
void set_line(const irep_idt &line)
void set_function(const irep_idt &function)
Expression to hold a symbol (variable).
const irep_idt & get_identifier() const
irep_idt base_name
Base (non-scoped) name.
source_locationt location
Source code location of definition of symbol.
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
typet type
Type of symbol.
irep_idt name
The unique identifier.
irep_idt mode
Language mode.
The Boolean constant true.
void parse_unwindset(const std::list< std::string > &unwindset, abstract_goto_modelt &goto_model, message_handlert &message_handler)
static void generate_contract_constraints(symbol_tablet &symbol_table, goto_convertt &converter, exprt &instantiated_clause, const irep_idt &mode, const std::function< void(goto_programt &)> &is_fresh_update, goto_programt &program, const source_locationt &location)
This function generates instructions for all contract constraint, i.e., assumptions and assertions ba...
static const code_with_contract_typet & get_contract(const irep_idt &function, const namespacet &ns)
static void throw_on_unsupported(const goto_programt &program)
Throws an exception if a contract uses unsupported constructs like:
Verify and use annotated invariants and pre/post-conditions.
static const std::map< dfcc_funt, int > to_unwind
set of functions that need to be unwound to assigns clause size with corresponding loop identifiers.
auto expr_try_dynamic_cast(TExpr &base) -> typename detail::expr_try_dynamic_cast_return_typet< T, TExpr >::type
Try to cast a reference to a generic exprt to a specific derived class.
exprt boolean_negate(const exprt &src)
negate a Boolean expression, possibly removing a not_exprt, and swapping false and true
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.
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.
Function Inlining This gives a number of different interfaces to the function inlining functionality ...
#define Forall_goto_program_instructions(it, program)
Havoc function assigns clauses.
std::set< exprt > assignst
std::optional< code_with_contract_typet > get_contract(const irep_idt &function_identifier, const namespacet &ns)
void add_pragma_disable_assigns_check(source_locationt &location)
Adds a pragma on a source_locationt to disable inclusion checking.
Specify write set in function contracts.
const std::string & id2string(const irep_idt &d)
Field-insensitive, location-sensitive may-alias analysis.
natural_loops_mutablet::natural_loopt loopt
API to expression classes for 'mathematical' expressions.
const lambda_exprt & to_lambda_expr(const exprt &expr)
Cast an exprt to a lambda_exprt.
Predicates to specify memory footprint in function contracts.
natural_loops_templatet< goto_programt, goto_programt::targett, goto_programt::target_less_than > natural_loops_mutablet
static void nondet_static(const namespacet &ns, goto_modelt &goto_model, const irep_idt &fct_name)
Nondeterministically initializes global scope variables in a goto-function.
Nondeterministically initializes global scope variables, except for constants (such as string literal...
void remove_skip(goto_programt &goto_program, goto_programt::targett begin, goto_programt::targett end)
remove unnecessary skip statements
#define UNREACHABLE
This should be used to mark dead code.
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
#define PRECONDITION(CONDITION)
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
exprt conjunction(exprt a, exprt b)
Conjunction of two expressions.
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
void generate_history_variables_initialization(symbol_table_baset &symbol_table, exprt &clause, const irep_idt &mode, goto_programt &program)
This function generates all the instructions required to initialize history variables.
bool is_assignment_to_instrumented_variable(const goto_programt::const_targett &target, std::string var_name)
Return true if target is an assignment to an instrumented variable with name var_name.
void insert_before_and_update_jumps(goto_programt &destination, goto_programt::targett &target, const goto_programt::instructiont &i)
Insert a goto instruction before a target instruction iterator and update targets of all jumps that p...
void infer_loop_assigns(const local_may_aliast &local_may_alias, const loopt &loop, assignst &assigns)
Infer loop assigns using alias analysis result local_may_alias.
bool is_loop_free(const goto_programt &goto_program, const namespacet &ns, messaget &log)
Returns true iff the given program is loop-free, i.e.
exprt get_loop_assigns(const goto_programt::const_targett &loop_end)
replace_history_parametert replace_history_loop_entry(symbol_table_baset &symbol_table, const exprt &expr, const source_locationt &location, const irep_idt &mode)
This function recursively identifies the "loop_entry" expressions within expr and replaces them with ...
bool is_transformed_loop_head(const goto_programt::const_targett &target)
Return true if target is the head of some transformed loop.
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.
void widen_assigns(assignst &assigns, const namespacet &ns)
Widen expressions in assigns with the following strategy.
void simplify_gotos(goto_programt &goto_program, const namespacet &ns)
Turns goto instructions IF cond GOTO label where the condition statically simplifies to false into SK...
exprt get_loop_invariants(const goto_programt::const_targett &loop_end, const bool check_side_effect)
bool is_transformed_loop_end(const goto_programt::const_targett &target)
Return true if target is the end of some transformed loop.
exprt get_loop_decreases(const goto_programt::const_targett &loop_end, const bool check_side_effect)
unsigned get_suffix_unsigned(const std::string &str, const std::string &prefix)
Convert the suffix digits right after prefix of str into unsigned.
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.
#define IN_LOOP_HAVOC_BLOCK