void rw_sett::assign(const exprt &lhs, const exprt &rhs) { read(rhs); read_write_rec(lhs, false, true, "", guardt()); }
void goto_checkt::goto_check(goto_functiont &goto_function) { { const symbolt *init_symbol; if(!ns.lookup(CPROVER_PREFIX "initialize", init_symbol)) mode=init_symbol->mode; } assertions.clear(); local_bitvector_analysist local_bitvector_analysis_obj(goto_function); local_bitvector_analysis=&local_bitvector_analysis_obj; goto_programt &goto_program=goto_function.body; Forall_goto_program_instructions(it, goto_program) { t=it; goto_programt::instructiont &i=*it; new_code.clear(); // we clear all recorded assertions if // 1) we want to generate all assertions or // 2) the instruction is a branch target if(retain_trivial || i.is_target()) assertions.clear(); check(i.guard); // magic ERROR label? for(optionst::value_listt::const_iterator l_it=error_labels.begin(); l_it!=error_labels.end(); l_it++) { if(std::find(i.labels.begin(), i.labels.end(), *l_it)!=i.labels.end()) { goto_program_instruction_typet type= enable_assert_to_assume?ASSUME:ASSERT; goto_programt::targett t=new_code.add_instruction(type); t->guard=false_exprt(); t->source_location=i.source_location; t->source_location.set_property_class("error label"); t->source_location.set_comment("error label "+*l_it); t->source_location.set("user-provided", true); } } if(i.is_other()) { const irep_idt &statement=i.code.get(ID_statement); if(statement==ID_expression) { check(i.code); } else if(statement==ID_printf) { forall_operands(it, i.code) check(*it); } } else if(i.is_assign()) { const code_assignt &code_assign=to_code_assign(i.code); check(code_assign.lhs()); check(code_assign.rhs()); // the LHS might invalidate any assertion invalidate(code_assign.lhs()); } else if(i.is_function_call()) { const code_function_callt &code_function_call= to_code_function_call(i.code); // for Java, need to check whether 'this' is null // on non-static method invocations if(mode==ID_java && enable_pointer_check && !code_function_call.arguments().empty() && code_function_call.function().type().id()==ID_code && to_code_type(code_function_call.function().type()).has_this()) { exprt pointer=code_function_call.arguments()[0]; local_bitvector_analysist::flagst flags= local_bitvector_analysis->get(t, pointer); if(flags.is_unknown() || flags.is_null()) { notequal_exprt not_eq_null(pointer, gen_zero(pointer.type())); add_guarded_claim( not_eq_null, "this is null on method invokation", "pointer dereference", i.source_location, pointer, guardt()); } } forall_operands(it, code_function_call) check(*it); // the call might invalidate any assertion assertions.clear(); } else if(i.is_return()) { if(i.code.operands().size()==1) { check(i.code.op0()); // the return value invalidate any assertion invalidate(i.code.op0()); } } else if(i.is_throw()) { if(i.code.get_statement()==ID_expression && i.code.operands().size()==1 && i.code.op0().operands().size()==1) { // must not throw NULL exprt pointer=i.code.op0().op0(); if(pointer.type().subtype().get(ID_identifier)!="java::java.lang.AssertionError") { notequal_exprt not_eq_null(pointer, gen_zero(pointer.type())); add_guarded_claim( not_eq_null, "throwing null", "pointer dereference", i.source_location, pointer, guardt()); } } // this has no successor assertions.clear(); } else if(i.is_assert()) { if(i.source_location.get_bool("user-provided") && i.source_location.get_property_class()!="error label" && !enable_assertions) i.type=SKIP; } else if(i.is_assume()) { if(!enable_assumptions) i.type=SKIP; } else if(i.is_dead()) { if(enable_pointer_check) { assert(i.code.operands().size()==1); const symbol_exprt &variable=to_symbol_expr(i.code.op0()); // is it dirty? if(local_bitvector_analysis->dirty(variable)) { // need to mark the dead variable as dead goto_programt::targett t=new_code.add_instruction(ASSIGN); exprt address_of_expr=address_of_exprt(variable); exprt lhs=ns.lookup(CPROVER_PREFIX "dead_object").symbol_expr(); if(!base_type_eq(lhs.type(), address_of_expr.type(), ns)) address_of_expr.make_typecast(lhs.type()); exprt rhs=if_exprt( side_effect_expr_nondett(bool_typet()), address_of_expr, lhs, lhs.type()); t->source_location=i.source_location; t->code=code_assignt(lhs, rhs); t->code.add_source_location()=i.source_location; } } } else if(i.is_end_function()) { if(i.function==goto_functionst::entry_point() && enable_memory_leak_check) { const symbolt &leak=ns.lookup(CPROVER_PREFIX "memory_leak"); const symbol_exprt leak_expr=leak.symbol_expr(); // add self-assignment to get helpful counterexample output goto_programt::targett t=new_code.add_instruction(); t->make_assignment(); t->code=code_assignt(leak_expr, leak_expr); source_locationt source_location; source_location.set_function(i.function); equal_exprt eq(leak_expr, gen_zero(ns.follow(leak.type))); add_guarded_claim( eq, "dynamically allocated memory never freed", "memory-leak", source_location, eq, guardt()); } } for(goto_programt::instructionst::iterator i_it=new_code.instructions.begin(); i_it!=new_code.instructions.end(); i_it++) { if(i_it->source_location.is_nil()) { i_it->source_location.id(irep_idt()); if(it->source_location.get_file()!=irep_idt()) i_it->source_location.set_file(it->source_location.get_file()); if(it->source_location.get_line()!=irep_idt()) i_it->source_location.set_line(it->source_location.get_line()); if(it->source_location.get_function()!=irep_idt()) i_it->source_location.set_function(it->source_location.get_function()); if(it->source_location.get_column()!=irep_idt()) i_it->source_location.set_column(it->source_location.get_column()); } if(i_it->function==irep_idt()) i_it->function=it->function; } // insert new instructions -- make sure targets are not moved while(!new_code.instructions.empty()) { goto_program.insert_before_swap(it, new_code.instructions.front()); new_code.instructions.pop_front(); it++; } }
void simulator_loop_detectiont::build_loop_recurrence( symex_target_equationt &equation, goto_symex_statet &end_state, loop_begint &loop_begin, const exprt ¶meter_expr, std::list<exprt> &recurrences, std::map<goto_programt::const_targett,code_assignt> &instructions, std::map<goto_programt::const_targett,exprt> &closed_forms) { // find start in equation symex_target_equationt::SSA_stepst::iterator start_it=equation.get_SSA_step(loop_begin.state_nr); // build the problem std::map<exprt, exprt> problem; std::set<exprt> start_values, end_values; for(symex_target_equationt::SSA_stepst::iterator e_it=start_it; e_it!=equation.SSA_steps.end(); e_it++) { symex_target_equationt::SSA_stept &s=*e_it; if(s.is_assignment()) { const exprt &lhs=s.ssa_lhs; const exprt &rhs=s.ssa_rhs; // compute start/end values start_values.insert(rename(loop_begin.state, s.original_lhs_object)); end_values.insert(rename(end_state, s.original_lhs_object)); if (!s.original_lhs_object.get_bool("induction_symbol")) { problem[lhs]=rhs; #if 0 std::cout << "Part of the problem: " << from_expr (ns, "", lhs) << " := " << from_expr (ns, "", rhs) << std::endl; #endif } } } // create a new parameter variable loop_infos.push_back(loop_infot()); loop_infos.back().parameter=parameter_expr; // solve the problem replace_mapt solution; recurrence_solver::solve_recurrence(parameter_expr, start_values, end_values, loop_begin.state, end_state, problem, solution, concrete_model.ns); // put in solution for(symex_target_equationt::SSA_stepst::iterator e_it=start_it; e_it!=equation.SSA_steps.end(); e_it++) { bool has_recurrence = false; symex_target_equationt::SSA_stept &s=*e_it; #ifdef DEBUG std::cout << "*** " << s.pc->location << std::endl; #endif if(s.is_assignment()) { if (solution[s.ssa_lhs].id()!=ID_nondet_symbol && solution[s.ssa_lhs] != s.ssa_rhs && !s.ssa_lhs.get_bool("induction_symbol")) has_recurrence = true; #ifdef DEBUG std::cout << "ASSIGNMENT BEFORE: " << from_expr(ns, "", s.ssa_lhs) << " := " << from_expr(ns, "", s.rhs) << std::endl; #endif if(!s.original_lhs_object.get_bool("induction_symbol")) s.ssa_rhs=solution[s.ssa_lhs]; #ifdef DEBUG std::cout << "ASSIGNMENT AFTER: " << from_expr(ns, "", s.ssa_lhs) << " := " << from_expr(ns, "", s.rhs) << std::endl; #endif // fix cond assert(s.cond_expr.id()==ID_equal && s.cond_expr.operands().size()==2); s.cond_expr.op1()=s.ssa_rhs; // remember the recurrence instruction and the // closed form for WP computation code_assignt instruction(s.ssa_lhs, solution[s.ssa_lhs]); end_state.get_original_name(instruction); instructions[s.source.pc] = instruction; if(has_recurrence) { exprt equality=equal_exprt(s.ssa_lhs, solution[s.ssa_lhs]); if(!s.ssa_lhs.get_bool("induction_symbol")) { closed_forms[s.source.pc]=equality; } } } else if(s.is_assert()) { #ifdef DEBUG std::cout << "ASSERT: " << from_expr(ns, "", s.cond) << std::endl; #endif } else if(s.is_assume()) { #ifdef DEBUG std::cout << "ASSUME: " << from_expr(ns, "", s.cond) << std::endl; #endif } } // assign parameter, so we can grab it from a counterexample exprt tmp(parameter_expr); equation.assignment( guardt(), to_symbol_expr(parameter_expr), to_symbol_expr(parameter_expr), to_symbol_expr(parameter_expr), to_symbol_expr(parameter_expr), tmp, loop_begin.state.source, symex_targett::STATE); // now clean up the recurrence predicates used for refinement recurrence_solver::cleanup_recurrence_predicates(equation, loop_begin.state_nr, end_state, problem, closed_forms, recurrences, concrete_model.ns); }