36 const std::unordered_map<exprt, exprt, irep_hash> &tmp_post_map)
39 for(
const auto &tmp_post_entry : tmp_post_map)
43 "tmp_post variables must be symbol expression.");
44 const auto &tmp_post_symbol =
45 expr_dynamic_cast<symbol_exprt>(tmp_post_entry.first);
46 r.insert(tmp_post_symbol, tmp_post_entry.second);
59 std::vector<exprt> result;
60 for(
const auto &e : symbols)
62 if(e.type().id() == ID_unsignedbv)
71 if((e.type().id() == ID_signedbv))
74 result.push_back(
unary_exprt(ID_loop_entry, e, e.type()));
76 if((e.type().id() == ID_pointer))
97 natural_loops(function_p.second.body);
103 for(
const auto &loop_head_and_content : natural_loops.
loop_map)
106 if(loop_head_and_content.second.size() <= 1)
111 loop_head_and_content.first, loop_head_and_content.second);
113 loop_idt new_id(function_p.first, loop_end->loop_number);
114 loop_cfg_infot cfg_info(function_p.second, loop_head_and_content.second);
116 log.
progress() <<
"Initialize candidates for the loop at "
131 loop_end->is_goto() &&
134 loop_end->turn_into_skip();
139 if(loop_end->condition().find(ID_C_spec_loop_invariant).is_nil())
143 loop_end->loop_number,
146 if(loop_head->has_condition())
154 if(loop_end->condition().find(ID_C_spec_assigns).is_nil())
160 local_may_alias, loop_head_and_content.second,
assigns_map[new_id]);
166 if(
auto symbol_expr = expr_try_dynamic_cast<symbol_exprt>(*it))
193 const exprt &checked_pointer,
194 const std::list<loop_idt> cause_loop_ids)
196 auto new_assign = checked_pointer;
200 for(
const auto &loop_id : cause_loop_ids)
203 if(new_assign.id() == ID_index || new_assign.id() == ID_dereference)
213 const auto &source_location =
225 new_assign.add_source_location() = source_location;
231 INVARIANT(
false,
"Failed to synthesize a new assigns target.");
238 for(
const auto &instruction : goto_function.second.body.instructions)
241 if(!instruction.is_assign() || instruction.assign_lhs().id() != ID_symbol)
244 const auto symbol_lhs =
245 expr_try_dynamic_cast<symbol_exprt>(instruction.assign_lhs());
249 id2string(symbol_lhs->get_identifier()).find(
"tmp::tmp_post") !=
252 tmp_post_map[instruction.assign_lhs()] = instruction.assign_rhs();
258 std::set<symbol_exprt>
261 const exprt &new_clause,
262 const std::set<exprt> &live_vars)
267 std::set<symbol_exprt> result;
268 for(
const auto &e : live_vars)
273 for(
auto it = result.begin(); it != result.end();)
277 it = result.erase(it);
287 const exprt &violated_predicate)
293 return violated_predicate;
297 const exprt &checked_pointer)
304 checked_pointer,
unary_exprt(ID_loop_entry, checked_pointer));
308 const std::vector<exprt> terminal_symbols,
311 const std::vector<cext> &cexs)
328 expr_sett leafexprs(terminal_symbols.begin(), terminal_symbols.end());
334 start_args.push_back(&leaf_g);
342 if(partition.size() <= 1)
344 return partition.front() == 1;
347 start_args.push_back(&plus_g);
353 start_bool_args.push_back(&and_g);
356 start_bool_args.push_back(&equal_g);
359 start_bool_args.push_back(&le_g);
362 start_bool_args.push_back(<_g);
370 size_t size_bound = 0;
373 size_t count_all = 0;
374 size_t count_filtered = 0;
382 for(
auto strengthening_candidate : start_bool_ph.
enumerate(size_bound))
387 new_in_clauses[cause_loop_id] =
388 and_exprt(new_in_clauses[cause_loop_id], strengthening_candidate);
390 new_pos_clauses[cause_loop_id] =
391 and_exprt(new_pos_clauses[cause_loop_id], strengthening_candidate);
412 const auto &return_cex = verifier.
verify();
414 !return_cex.has_value() ||
415 (verifier.
properties.at(violation_id).status !=
417 return_cex->violation_type !=
419 return_cex->violation_type !=
422 log.
progress() <<
"Quick filter: " << count_filtered <<
" out of "
423 << count_all <<
" candidates were filtered out.\n";
424 return strengthening_candidate;
447 std::set<symbol_exprt> dependent_symbols;
449 std::vector<exprt> terminal_symbols;
452 auto return_cex = verifier.
verify();
455 std::vector<cext> cexs;
457 while(return_cex.has_value())
459 cexs.push_back(return_cex.value());
463 switch(return_cex->violation_type)
466 new_invariant_clause =
471 new_invariant_clause =
477 return_cex->checked_pointer, return_cex->cause_loop_ids);
483 return_cex->cause_loop_ids.front(),
484 new_invariant_clause,
485 return_cex->live_variables);
490 return_cex->cause_loop_ids.front(),
496 INVARIANT(
false,
"unsupported violation type");
504 INVARIANT(!return_cex->cause_loop_ids.empty(),
"No cause loop found!");
507 "failed to synthesized meaningful clause");
513 const auto &cause_loop_id = return_cex->cause_loop_ids.front();
516 cause_loop_id, new_invariant_clause, return_cex->live_variables);
520 return_cex->violation_location ==
555 return_cex = verifier.
verify();
561 return combined_invariant;
signedbv_typet signed_short_int_type()
Evaluate if an expression is consistent with examples.
Classes providing CFG-based information about symbols to guide simplifications in function and loop a...
Operator to return the address of an object.
Enumerator that enumerates binary functional expressions.
Evaluator for checking if an expression is consistent with a given set of test cases (positive exampl...
Verifier that take a goto program as input, and output formatted counterexamples for counterexample-g...
std::optional< cext > verify()
Verify goto_model.
irep_idt target_violation_id
propertiest properties
Result counterexample.
@ cex_not_hold_upon_entry
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
std::map< loop_idt, std::set< exprt > > assigns_map
Synthesized assigns clauses.
invariant_mapt synthesize_all() override
This synthesizer guarantees that, with the synthesized loop contracts, all checks in the annotated GO...
exprt synthesize(loop_idt loop_id) override
Synthesize loop invariant for a specified loop in the goto_model.
exprt synthesize_range_predicate(const exprt &violated_predicate)
Synthesize range predicate for OOB violation with violated_predicate.
const symbol_tablet original_symbol_table
Symbol table of the input goto model.
std::set< symbol_exprt > compute_dependent_symbols(const loop_idt &cause_loop_id, const exprt &new_clause, const std::set< exprt > &live_vars)
Compute the dependent symbols for a loop with invariant-not-preserved violation which happen after ne...
invariant_mapt in_invariant_clause_map
Synthesize invariant of form (in_inv || !guard) && (!guard -> pos_inv)
void build_tmp_post_map()
Scan all ASSIGN instructions to build the map from tmp_post variables to their original variables.
std::unordered_map< exprt, exprt, irep_hash > tmp_post_map
Map from tmp_post variables to their original variables.
void init_candidates()
Initialize invariants as true for all unannotated loops.
invariant_mapt pos_invariant_clause_map
invariant_mapt neg_guards
void synthesize_assigns(const exprt &checked_pointer, const std::list< loop_idt > cause_loop_ids)
Synthesize assigns target and update assigns_map.
exprt synthesize_strengthening_clause(const std::vector< exprt > terminal_symbols, const loop_idt &cause_loop_id, const irep_idt &violation_id, const std::vector< cext > &cexs)
Synthesize strengthening clause for invariant-not-preserved violation.
exprt synthesize_same_object_predicate(const exprt &checked_pointer)
Synthesize same object predicate for null-pointer violation for checked_pointer.
Factory for enumerator that can be used to represent a tree grammar.
void attach_productions(const std::string &id, const enumeratorst &enumerators)
Attach enumerators to the placeholder with id.
Base class for all expressions.
The Boolean constant false.
function_mapt function_map
goto_functionst goto_functions
GOTO functions.
instructionst::iterator targett
A class containing utility functions for havocing expressions.
Enumerator that enumerates leaf expressions from a given list.
void erase_locals(std::set< exprt > &exprs)
source_locationt source_location
static const commandt reset
return to default formatting, as defined by the terminal
static const commandt green
render text with green foreground color
mstreamt & progress() const
mstreamt & result() const
The offset (in bytes) of a pointer relative to the object.
Placeholders for actual enumerators, which represent nonterminals.
expr_sett enumerate(const std::size_t size) const override
Replace a symbol expression by a given expression.
const symbolt * lookup(const irep_idt &name) const
Find a symbol in the symbol table for read-only access.
The Boolean constant true.
Semantic type conversion.
Generic base class for unary expressions.
std::unordered_set< exprt, irep_hash > expr_sett
bool has_prefix(const std::string &s, const std::string &prefix)
static exprt evaluator(const std::unordered_map< exprt, exprt, irep_hash > &memory, const decision_proceduret &solver, exprt src, const namespacet &ns)
std::vector< exprt > construct_terminals(const std::set< symbol_exprt > &symbols)
void replace_tmp_post(exprt &dest, const std::unordered_map< exprt, exprt, irep_hash > &tmp_post_map)
Enumerative Loop Contracts Synthesizer.
std::list< const enumerator_baset * > enumeratorst
std::list< std::size_t > partitiont
static bool find_symbols(symbol_kindt, const typet &, std::function< bool(const symbol_exprt &)>, std::unordered_set< irep_idt > &bindings, const std::vector< irep_idt > &subs_to_find)
Find identifiers with id ID_symbol of the sub expressions and the subs with ID in subs_to_find consid...
Utilities for building havoc code for expressions.
const std::string & id2string(const irep_idt &d)
Field-insensitive, location-sensitive may-alias analysis.
void get_assigns(const local_may_aliast &local_may_alias, const loopt &loop, assignst &assigns)
Helper functions for k-induction and loop invariants.
Compute natural loops in a goto_function.
exprt same_object(const exprt &p1, const exprt &p2)
exprt pointer_object(const exprt &p)
Various predicates over pointers in programs.
@ FAIL
The property was violated.
exprt simplify_expr(exprt src, const namespacet &ns)
#define UNREACHABLE
This should be used to mark dead code.
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
bool can_cast_expr< symbol_exprt >(const exprt &base)
bool is_constant(const typet &type)
This method tests, if the given typet is a constant.
Loop id used to identify loops.
invariant_mapt combine_in_and_post_invariant_clauses(const invariant_mapt &in_clauses, const invariant_mapt &post_clauses, const invariant_mapt &neg_guards)
Combine invariant of form (in_inv || !guard) && (!guard -> pos_inv)
goto_programt::targett get_loop_head(const unsigned int target_loop_number, goto_functiont &function)
Find and return the first instruction of the natural loop with loop_number in function.
void widen_assigns(assignst &assigns, const namespacet &ns)
Widen expressions in assigns with the following strategy.
goto_programt::targett get_loop_end_from_loop_head_and_content_mutable(const goto_programt::targett &loop_head, const loop_templatet< goto_programt::targett, goto_programt::target_less_than > &loop)
Find the goto instruction of loop that jumps to loop_head
std::map< loop_idt, exprt > invariant_mapt