void goto_inlinet::replace_return( goto_programt &dest, const exprt &lhs, const exprt &constrain) { for(goto_programt::instructionst::iterator it=dest.instructions.begin(); it!=dest.instructions.end(); it++) { if(it->is_return()) { if(lhs.is_not_nil()) { goto_programt tmp; goto_programt::targett assignment=tmp.add_instruction(ASSIGN); const code_return2t &ret = to_code_return2t(it->code); code_assignt code_assign(lhs, migrate_expr_back(ret.operand)); // this may happen if the declared return type at the call site // differs from the defined return type if(code_assign.lhs().type()!= code_assign.rhs().type()) code_assign.rhs().make_typecast(code_assign.lhs().type()); migrate_expr(code_assign, assignment->code); assignment->location=it->location; assignment->local_variables=it->local_variables; assignment->function=it->location.get_function(); assert(constrain.is_nil()); // bp_constrain gumpf reomved dest.insert_swap(it, *assignment); it++; } else if(!is_nil_expr(it->code)) { // Encode evaluation of return expr, so that returns with pointer // derefs in them still get dereferenced, even when the result is // discarded. goto_programt tmp; goto_programt::targett expression=tmp.add_instruction(OTHER); expression->make_other(); expression->location=it->location; expression->function=it->location.get_function(); expression->local_variables=it->local_variables; const code_return2t &ret = to_code_return2t(it->code); expression->code = code_expression2tc(ret.operand); dest.insert_swap(it, *expression); it++; } it->make_goto(--dest.instructions.end()); } } }
void goto_checkt::add_guarded_claim(const exprt &_expr, const std::string &comment, const std::string &property, const locationt &location, const guardt &guard) { bool all_claims = options.get_bool_option("all-claims"); exprt expr(_expr); // first try simplifier on it if (!options.get_bool_option("no-simplify")) { expr2tc tmpexpr; migrate_expr(expr, tmpexpr); base_type(tmpexpr, ns); expr = migrate_expr_back(tmpexpr); simplify(expr); } if (!all_claims && expr.is_true()) return; // add the guard exprt guard_expr = migrate_expr_back(guard.as_expr()); exprt new_expr; if (guard_expr.is_true()) new_expr.swap(expr); else { new_expr = exprt("=>", bool_typet()); new_expr.move_to_operands(guard_expr, expr); } if (assertions.insert(new_expr).second) { goto_programt::targett t = new_code.add_instruction(ASSERT); migrate_expr(new_expr, t->guard); t->location = location; t->location.comment(comment); t->location.property(property); } }
void goto_inlinet::parameter_assignments( const locationt &location, const code_typet &code_type, const exprt::operandst &arguments, goto_programt &dest) { // iterates over the operands exprt::operandst::const_iterator it1=arguments.begin(); goto_programt::local_variablest local_variables; const code_typet::argumentst &argument_types= code_type.arguments(); // iterates over the types of the arguments for(code_typet::argumentst::const_iterator it2=argument_types.begin(); it2!=argument_types.end(); it2++) { // if you run out of actual arguments there was a mismatch if(it1==arguments.end()) { err_location(location); throw "function call: not enough arguments"; } const exprt &argument=static_cast<const exprt &>(*it2); // this is the type the n-th argument should be const typet &arg_type=ns.follow(argument.type()); const irep_idt &identifier=argument.cmt_identifier(); if(identifier=="") { err_location(location); throw "no identifier for function argument"; } { const symbolt &symbol=ns.lookup(identifier); goto_programt::targett decl=dest.add_instruction(); decl->make_other(); exprt tmp = code_declt(symbol_expr(symbol)); migrate_expr(tmp, decl->code); decl->location=location; decl->function=location.get_function(); decl->local_variables=local_variables; } local_variables.insert(identifier); // nil means "don't assign" if(it1->is_nil()) { } else { // this is the actual parameter exprt actual(*it1); // it should be the same exact type type2tc arg_type_2, actual_type_2; migrate_type(arg_type, arg_type_2); migrate_type(actual.type(), actual_type_2); if (!base_type_eq(arg_type_2, actual_type_2, ns)) { const typet &f_argtype = ns.follow(arg_type); const typet &f_acttype = ns.follow(actual.type()); // we are willing to do some conversion if((f_argtype.id()=="pointer" && f_acttype.id()=="pointer") || (f_argtype.is_array() && f_acttype.id()=="pointer" && f_argtype.subtype()==f_acttype.subtype())) { actual.make_typecast(arg_type); } else if((f_argtype.id()=="signedbv" || f_argtype.id()=="unsignedbv" || f_argtype.is_bool()) && (f_acttype.id()=="signedbv" || f_acttype.id()=="unsignedbv" || f_acttype.is_bool())) { actual.make_typecast(arg_type); } else { err_location(location); str << "function call: argument `" << identifier << "' type mismatch: got " << from_type(ns, identifier, it1->type()) << ", expected " << from_type(ns, identifier, arg_type); throw 0; } } // adds an assignment of the actual parameter to the formal parameter code_assignt assignment(symbol_exprt(identifier, arg_type), actual); assignment.location()=location; dest.add_instruction(ASSIGN); dest.instructions.back().location=location; migrate_expr(assignment, dest.instructions.back().code); dest.instructions.back().local_variables=local_variables; dest.instructions.back().function=location.get_function(); } it1++; } if(it1!=arguments.end()) { // too many arguments -- we just ignore that, no harm done } }
void goto_checkt::check_rec(const exprt &expr, guardt &guard, bool address) { if (address) { if (expr.id() == "dereference") { assert(expr.operands().size() == 1); check_rec(expr.op0(), guard, false); } else if (expr.id() == "index") { assert(expr.operands().size() == 2); check_rec(expr.op0(), guard, true); check_rec(expr.op1(), guard, false); } else { forall_operands(it, expr) check_rec(*it, guard, true); } return; } if (expr.is_address_of()) { assert(expr.operands().size() == 1); check_rec(expr.op0(), guard, true); return; } else if (expr.is_and() || expr.id() == "or") { if (!expr.is_boolean()) throw expr.id_string() + " must be Boolean, but got " + expr.pretty(); unsigned old_guards = guard.size(); for (unsigned i = 0; i < expr.operands().size(); i++) { const exprt &op = expr.operands()[i]; if (!op.is_boolean()) throw expr.id_string() + " takes Boolean operands only, but got " + op.pretty(); check_rec(op, guard, false); if (expr.id() == "or") { exprt tmp(op); tmp.make_not(); expr2tc tmp_expr; migrate_expr(tmp, tmp_expr); guard.move(tmp_expr); } else { expr2tc tmp; migrate_expr(op, tmp); guard.add(tmp); } } guard.resize(old_guards); return; } else if (expr.id() == "if") { if (expr.operands().size() != 3) throw "if takes three arguments"; if (!expr.op0().is_boolean()) { std::string msg = "first argument of if must be boolean, but got " + expr.op0().to_string(); throw msg; } check_rec(expr.op0(), guard, false); { unsigned old_guard = guard.size(); expr2tc tmp; migrate_expr(expr.op0(), tmp); guard.add(tmp); check_rec(expr.op1(), guard, false); guard.resize(old_guard); } { unsigned old_guard = guard.size(); exprt tmp(expr.op0()); tmp.make_not(); expr2tc tmp_expr; migrate_expr(tmp, tmp_expr); guard.move(tmp_expr); check_rec(expr.op2(), guard, false); guard.resize(old_guard); } return; } forall_operands(it, expr) check_rec(*it, guard, false); if (expr.id() == "index") { bounds_check(expr, guard); } else if (expr.id() == "/") { div_by_zero_check(expr, guard); if (expr.type().id() == "signedbv") { overflow_check(expr, guard); } else if (expr.type().id() == "floatbv") { nan_check(expr, guard); } } else if (expr.id() == "+" || expr.id() == "-" || expr.id() == "*" || expr.id() == "unary-" || expr.id() == "typecast") { if (expr.type().id() == "signedbv") { overflow_check(expr, guard); } else if (expr.type().id() == "floatbv") { nan_check(expr, guard); } } else if (expr.id() == "<=" || expr.id() == "<" || expr.id() == ">=" || expr.id() == ">") { pointer_rel_check(expr, guard); } else if (expr.id() == "mod") { div_by_zero_check(expr, guard); if (expr.type().id() == "signedbv") { overflow_check(expr, guard); } else if (expr.type().id() == "floatbv") { nan_check(expr, guard); } } }
void rw_sett::read_write_rec( const exprt &expr, bool r, bool w, const std::string &suffix, const guardt &guard) { if(expr.id()=="symbol" && !expr.has_operands()) { const symbol_exprt &symbol_expr=to_symbol_expr(expr); const symbolt *symbol; if(!ns.lookup(symbol_expr.get_identifier(), symbol)) { if(!symbol->static_lifetime /*&& expr.type().id()=="pointer"*/) { return; // ignore for now } if(symbol->name=="c::__ESBMC_alloc" || symbol->name=="c::__ESBMC_alloc_size" || symbol->name=="c::stdin" || symbol->name=="c::stdout" || symbol->name=="c::stderr" || symbol->name=="c::sys_nerr") { return; // ignore for now } } irep_idt object=id2string(symbol_expr.get_identifier())+suffix; entryt &entry=entries[object]; entry.object=object; entry.r=entry.r || r; entry.w=entry.w || w; entry.guard = migrate_expr_back(guard.as_expr()); } else if(expr.id()=="member") { assert(expr.operands().size()==1); const std::string &component_name=expr.component_name().as_string(); read_write_rec(expr.op0(), r, w, "."+component_name+suffix, guard); } else if(expr.id()=="index") { // we don't distinguish the array elements for now assert(expr.operands().size()==2); std::string tmp; tmp = integer2string(binary2integer(expr.op1().value().as_string(), true),10); read_write_rec(expr.op0(), r, w, "["+suffix+tmp+"]", guard); read(expr.op1(), guard); } else if(expr.id()=="dereference") { assert(expr.operands().size()==1); read(expr.op0(), guard); exprt tmp(expr.op0()); expr2tc tmp_expr; migrate_expr(tmp, tmp_expr); dereference(target, tmp_expr, ns, value_sets); tmp = migrate_expr_back(tmp_expr); read_write_rec(tmp, r, w, suffix, guard); } else if(expr.is_address_of() || expr.id()=="implicit_address_of") { assert(expr.operands().size()==1); } else if(expr.id()=="if") { assert(expr.operands().size()==3); read(expr.op0(), guard); guardt true_guard(guard); expr2tc tmp_expr; migrate_expr(expr.op0(), tmp_expr); true_guard.add(tmp_expr); read_write_rec(expr.op1(), r, w, suffix, true_guard); guardt false_guard(guard); migrate_expr(gen_not(expr.op0()), tmp_expr); false_guard.add(tmp_expr); read_write_rec(expr.op2(), r, w, suffix, false_guard); } else { forall_operands(it, expr) read_write_rec(*it, r, w, suffix, guard); } }