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::goto_check(goto_programt &goto_program) { for (goto_programt::instructionst::iterator it = goto_program.instructions.begin(); it != goto_program.instructions.end(); it++) { goto_programt::instructiont &i = *it; new_code.clear(); assertions.clear(); check(migrate_expr_back(i.guard)); if (i.is_other()) { if (is_code_expression2t(i.code)) { check(migrate_expr_back(i.code)); } else if (is_code_printf2t(i.code)) { i.code->foreach_operand([this] (const expr2tc &e) { check(migrate_expr_back(e)); } ); } } else if (i.is_assign()) { const code_assign2t &assign = to_code_assign2t(i.code); check(migrate_expr_back(assign.target)); check(migrate_expr_back(assign.source)); } else if (i.is_function_call()) { i.code->foreach_operand([this] (const expr2tc &e) { check(migrate_expr_back(e)); } ); } else if (i.is_return()) { const code_return2t &ret = to_code_return2t(i.code); check(migrate_expr_back(ret.operand)); } for (goto_programt::instructionst::iterator i_it = new_code.instructions.begin(); i_it != new_code.instructions.end(); i_it++) { i_it->local_variables = it->local_variables; if (i_it->location.is_nil()) { if (!i_it->location.comment().as_string().empty()) it->location.comment(i_it->location.comment()); if (!i_it->location.property().as_string().empty()) it->location.property(i_it->location.property()); i_it->location = it->location; } if (i_it->function == "") i_it->function = it->function; if (i_it->function == "") i_it->function = it->function; } // insert new instructions -- make sure targets are not moved while (!new_code.instructions.empty()) { goto_program.insert_swap(it, new_code.instructions.front()); new_code.instructions.pop_front(); it++; } } }