26 std::optional<code_with_contract_typet>
30 auto contract_identifier =
"contract::" +
id2string(function_identifier);
32 if(ns.
lookup(contract_identifier, symbol_ptr))
40 return get_contract(function_identifier, ns).has_value();
45 auto text =
expr2c(src, ns);
47 return std::string(text, 0,
MAX_TEXT - 3) +
"...";
54 if(src.
id() == ID_dereference)
98 if(expr.
id() == ID_symbol)
100 else if(expr.
id() == ID_member)
111 if(lhs.
id() == ID_member)
116 else if(lhs.
id() == ID_index)
149 for(
auto &assigns_clause : assigns)
153 if(a.id() == ID_conditional_target_group)
157 for(
auto &target : targets.operands())
175 disjuncts.push_back(std::move(match));
185 if(lhs.
id() == ID_member)
188 else if(lhs.
id() == ID_index)
190 else if(lhs.
id() == ID_symbol)
193 return symbol_expr.get_identifier().starts_with(
202 if(lhs.
id() == ID_symbol)
205 return symbol_expr.get_identifier().starts_with(
"old::");
213 const std::string &prefix,
214 std::vector<std::pair<symbol_exprt, exprt>> &old_exprs)
216 for(std::size_t i = 0; i < old_exprs.size(); i++)
218 if(old_exprs[i].second == src)
219 return old_exprs[i].first;
222 auto index = old_exprs.size();
226 return old_exprs.back().first;
231 const std::string &prefix,
232 std::vector<std::pair<symbol_exprt, exprt>> &old_exprs)
234 if(src.
id() == ID_old)
249 const std::vector<std::pair<symbol_exprt, exprt>> &old_exprs,
254 for(
const auto &old_expr : old_exprs)
256 auto lhs = old_expr.first;
258 auto assignment_instruction =
260 dest.
add(std::move(assignment_instruction));
267 goto_functionst::function_mapt::value_type &f,
271 auto contract_identifier =
"contract::" +
id2string(f.first);
273 if(ns.
lookup(contract_identifier, symbol_ptr))
278 auto &body = f.second.body;
280 if(body.instructions.empty())
287 if(!contract.c_requires().empty())
291 for(
auto &assumption : contract.c_requires())
294 auto fixed_assumption =
add_function(f.first, assumption_instance);
296 fixed_assumption, fixed_assumption.source_location()));
301 std::vector<std::pair<symbol_exprt, exprt>> old_exprs;
302 const auto old_prefix =
"old::" +
id2string(f.first);
305 if(!contract.c_ensures().empty())
308 auto last = body.instructions.end();
309 if(std::prev(last)->is_end_function())
310 last = std::prev(last);
312 for(
auto &assertion : contract.c_ensures())
316 std::string
comment =
"postcondition";
317 if(contract.c_ensures().size() >= 2)
320 auto location = assertion.source_location();
321 location.set_function(f.first);
322 location.set_property_class(ID_postcondition);
325 auto replaced_assertion =
326 replace_old(assertion_instance, old_prefix, old_exprs);
328 auto fixed_assertion =
add_function(f.first, replaced_assertion);
330 auto assertion_instruction =
333 body.insert_before_swap(last, assertion_instruction);
339 !contract.c_assigns().empty() || !contract.c_requires().empty() ||
340 !contract.c_ensures().empty())
342 for(
auto &instruction : body.instructions)
343 instruction.transform(
344 [&old_prefix, &old_exprs](
exprt expr) -> std::optional<exprt> {
356 body.destructive_insert(body.instructions.begin(), add_at_beginning);
360 !contract.c_assigns().empty() || !contract.c_requires().empty() ||
361 !contract.c_ensures().empty())
363 for(
auto it = body.instructions.begin(); it != body.instructions.end();
368 const auto &lhs = it->assign_lhs();
378 auto assigns_assertion =
380 auto location = it->source_location();
381 location.set_property_class(
"assigns");
382 location.set_comment(
"assigns clause");
384 std::move(assigns_assertion), std::move(location));
385 body.insert_before_swap(it, assertion_instruction);
393 goto_functionst::function_mapt::value_type &f,
396 auto &body = f.second.body;
399 std::size_t call_site_counter = 0;
401 for(
auto it = body.instructions.begin(); it != body.instructions.end(); it++)
403 if(it->is_function_call())
405 const auto &
function = it->call_function();
406 if(
function.
id() == ID_symbol)
410 const auto contract_opt =
get_contract(symbol.name, ns);
412 if(!contract_opt.has_value())
415 auto &contract = contract_opt.value();
418 std::vector<std::pair<symbol_exprt, exprt>> old_exprs;
419 const auto old_prefix =
"old::" +
id2string(f.first) +
"::call-site-" +
431 const auto &arguments = it->call_arguments();
433 for(std::size_t p = 0; p < f_it->second.parameter_identifiers.size();
437 f_it->second.parameter_identifiers[p], parameters[p].type());
438 replace_symbol.
insert(p_symbol, arguments[p]);
442 const auto &call_lhs = it->call_lhs();
452 auto instantiated_precondition =
455 auto location = it->source_location();
456 location.set_property_class(ID_precondition);
457 location.set_comment(
458 id2string(symbol.display_name()) +
" precondition " +
459 expr2text(instantiated_precondition, ns));
461 auto replaced_precondition = instantiated_precondition;
462 replace_symbol(replaced_precondition);
469 for(
auto &assigns_clause_lambda : contract.c_assigns())
471 auto location = it->source_location();
473 auto assigns_clause =
476 if(assigns_clause.id() == ID_conditional_target_group)
479 auto replaced_condition = condition;
480 replace_symbol(replaced_condition);
482 const auto &targets =
486 for(
auto &target : targets)
490 auto replaced_lhs = target;
491 replace_symbol(replaced_lhs);
493 auto goto_instruction =
495 not_exprt(replaced_condition), location));
500 auto skip_instruction =
503 goto_instruction->complete_goto(skip_instruction);
508 const auto &lhs = assigns_clause;
511 auto replaced_lhs = lhs;
512 replace_symbol(replaced_lhs);
522 auto &location = it->source_location();
524 auto replaced_postcondition1 =
526 replace_symbol(replaced_postcondition1);
528 auto replaced_postcondition2 =
529 replace_old(replaced_postcondition1, old_prefix, old_exprs);
543 it->turn_into_skip();
546 body.destructive_insert(std::next(it), dest);
const code_with_contract_typet & to_code_with_contract_type(const typet &type)
Cast a typet to a code_with_contract_typet.
Operator to return the address of an object.
const parameterst & parameters() const
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Base class for all expressions.
std::vector< exprt > operandst
source_locationt & add_source_location()
const source_locationt & source_location() const
typet & type()
Return the type of the expression.
function_mapt function_map
symbol_tablet symbol_table
Symbol table.
goto_functionst goto_functions
GOTO functions.
A generic container class for the GOTO intermediate representation of one function.
static instructiont make_assumption(const exprt &g, const source_locationt &l=source_locationt::nil())
instructionst instructions
The list of instructions in the goto program.
void destructive_insert(const_targett target, goto_programt &p)
Inserts the given program p before target.
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())
targett add(instructiont &&instruction)
Adds a given instruction at the end.
static instructiont make_assertion(const exprt &g, const source_locationt &l=source_locationt::nil())
static instructiont make_incomplete_goto(const exprt &_cond, const source_locationt &l=source_locationt::nil())
const irep_idt & id() const
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().
Replace a symbol expression by a given expression.
void insert(const class symbol_exprt &old_expr, const exprt &new_expr)
Sets old_expr to be replaced by new_expr if we don't already have a replacement; otherwise does nothi...
A side_effect_exprt that returns a non-deterministically chosen value.
const irep_idt & get_file() const
void set_function(const irep_idt &function)
Expression to hold a symbol (variable)
source_locationt location
Source code location of definition of symbol.
typet type
Type of symbol.
The Boolean constant true.
static exprt conditional_cast(const exprt &expr, const typet &type)
std::string expr2c(const exprt &expr, const namespacet &ns, const expr2c_configurationt &configuration)
static std::string expr2text(const exprt &src, const namespacet &ns)
static bool is_symbol_member(const exprt &expr)
static bool is_procedure_local(const irep_idt &function_identifier, const exprt &lhs)
symbol_exprt find_old_expr(const exprt &src, const std::string &prefix, std::vector< std::pair< symbol_exprt, exprt >> &old_exprs)
void replace_function_calls_by_contracts(goto_functionst::function_mapt::value_type &f, const goto_modelt &goto_model)
static bool is_old(const exprt &lhs)
static exprt make_address(exprt src)
static exprt instantiate_contract_lambda(exprt src)
goto_programt old_assignments(const std::vector< std::pair< symbol_exprt, exprt >> &old_exprs, const source_locationt &source_location)
source_locationt add_function(irep_idt function_identifier, source_locationt src)
exprt assigns_match(const exprt &assigns, const exprt &lhs)
exprt replace_old(exprt src, const std::string &prefix, std::vector< std::pair< symbol_exprt, exprt >> &old_exprs)
void instrument_contracts(goto_modelt &goto_model)
static exprt make_assigns_assertion(irep_idt function_identifier, const exprt::operandst &assigns, const exprt &lhs)
void instrument_contract_checks(goto_functionst::function_mapt::value_type &f, const namespacet &ns)
bool has_contract(const irep_idt &function_identifier, const namespacet &ns)
exprt replace_source_location(exprt src, const source_locationt &source_location)
std::optional< code_with_contract_typet > get_contract(const irep_idt &function_identifier, const namespacet &ns)
Instrument Given Invariants.
const std::string & id2string(const irep_idt &d)
bool is_true(const literalt &l)
API to expression classes for 'mathematical' expressions.
const lambda_exprt & to_lambda_expr(const exprt &expr)
Cast an exprt to a lambda_exprt.
const dereference_exprt & to_dereference_expr(const exprt &expr)
Cast an exprt to a dereference_exprt.
exprt same_object(const exprt &p1, const exprt &p2)
Various predicates over pointers in programs.
void postcondition(const namespacet &ns, const value_sett &value_set, const symex_target_equationt &equation, const goto_symex_statet &s, exprt &dest)
void precondition(const namespacet &ns, value_setst &value_sets, const goto_programt::const_targett target, const symex_target_equationt &equation, const goto_symex_statet &s, exprt &dest, message_handlert &message_handler)
static std::string comment(const rw_set_baset::entryt &entry, bool write)
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
exprt disjunction(const exprt::operandst &op)
1) generates a disjunction for two or more operands 2) for one operand, returns the operand 3) return...
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
const multi_ary_exprt & to_multi_ary_expr(const exprt &expr)
Cast an exprt to a multi_ary_exprt.
const binary_exprt & to_binary_expr(const exprt &expr)
Cast an exprt to a binary_exprt.
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.