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_inlinet::parameter_assignments( const source_locationt &source_location, const irep_idt &function_name, const code_typet &code_type, const exprt::operandst &arguments, goto_programt &dest) { // iterates over the operands exprt::operandst::const_iterator it1=arguments.begin(); const code_typet::parameterst ¶meter_types= code_type.parameters(); // iterates over the types of the parameters for(code_typet::parameterst::const_iterator it2=parameter_types.begin(); it2!=parameter_types.end(); it2++) { const code_typet::parametert ¶meter=*it2; // this is the type the n-th argument should be const typet &par_type=ns.follow(parameter.type()); const irep_idt &identifier=parameter.get_identifier(); if(identifier==irep_idt()) { error().source_location=source_location; error() << "no identifier for function parameter" << eom; throw 0; } { const symbolt &symbol=ns.lookup(identifier); goto_programt::targett decl=dest.add_instruction(); decl->make_decl(); decl->code=code_declt(symbol.symbol_expr()); decl->code.add_source_location()=source_location; decl->source_location=source_location; decl->function=function_name; } // this is the actual parameter exprt actual; // if you run out of actual arguments there was a mismatch if(it1==arguments.end()) { warning().source_location=source_location; warning() << "call to `" << function_name << "': " << "not enough arguments, " << "inserting non-deterministic value" << eom; actual=side_effect_expr_nondett(par_type); } else actual=*it1; // nil means "don't assign" if(actual.is_nil()) { } else { // it should be the same exact type as the parameter, // subject to some exceptions if(!base_type_eq(par_type, actual.type(), ns)) { const typet &f_partype = ns.follow(par_type); const typet &f_acttype = ns.follow(actual.type()); // we are willing to do some conversion if((f_partype.id()==ID_pointer && f_acttype.id()==ID_pointer) || (f_partype.id()==ID_pointer && f_acttype.id()==ID_array && f_partype.subtype()==f_acttype.subtype())) { actual.make_typecast(par_type); } else if((f_partype.id()==ID_signedbv || f_partype.id()==ID_unsignedbv || f_partype.id()==ID_bool) && (f_acttype.id()==ID_signedbv || f_acttype.id()==ID_unsignedbv || f_acttype.id()==ID_bool)) { actual.make_typecast(par_type); } else { error().source_location=actual.find_source_location(); error() << "function call: argument `" << identifier << "' type mismatch: argument is `" // << from_type(ns, identifier, actual.type()) << actual.type().pretty() << "', parameter is `" << from_type(ns, identifier, par_type) << "'" << eom; throw 0; } } // adds an assignment of the actual parameter to the formal parameter code_assignt assignment(symbol_exprt(identifier, par_type), actual); assignment.add_source_location()=source_location; dest.add_instruction(ASSIGN); dest.instructions.back().source_location=source_location; dest.instructions.back().code.swap(assignment); dest.instructions.back().function=function_name; } if(it1!=arguments.end()) ++it1; } if(it1!=arguments.end()) { // too many arguments -- we just ignore that, no harm done } }