bool remove_function_pointerst::is_type_compatible( bool return_value_used, const code_typet &call_type, const code_typet &function_type) { // we are willing to ignore anything that's returned // if we call with 'void' if(!return_value_used) { } else if(type_eq(call_type.return_type(), empty_typet(), ns)) { // ok } else { if(!arg_is_type_compatible(call_type.return_type(), function_type.return_type())) return false; } // let's look at the parameters const code_typet::parameterst &call_parameters=call_type.parameters(); const code_typet::parameterst &function_parameters=function_type.parameters(); if(function_type.has_ellipsis() && function_parameters.empty()) { // always ok } else if(call_type.has_ellipsis() && call_parameters.empty()) { // always ok } else { // we are quite strict here, could be much more generous if(call_parameters.size()!=function_parameters.size()) return false; for(unsigned i=0; i<call_parameters.size(); i++) if(!arg_is_type_compatible(call_parameters[i].type(), function_parameters[i].type())) return false; } return true; }
bool cpp_typecheck_fargst::match( const code_typet &code_type, unsigned &distance, cpp_typecheckt &cpp_typecheck) const { distance=0; exprt::operandst ops = operands; const code_typet::argumentst &arguments=code_type.arguments(); if(arguments.size()>ops.size()) { // Check for default values. ops.reserve(arguments.size()); for(unsigned i=ops.size(); i<arguments.size(); i++) { const exprt &default_value= arguments[i].default_value(); if(default_value.is_nil()) return false; ops.push_back(default_value); } } else if(arguments.size()<ops.size()) { // check for ellipsis if(!code_type.has_ellipsis()) return false; } for(unsigned i=0; i<ops.size(); i++) { // read // http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/topic/com.ibm.xlcpp8a.doc/language/ref/implicit_conversion_sequences.htm // // The following are the three categories of conversion sequences in order from best to worst: // * Standard conversion sequences // * User-defined conversion sequences // * Ellipsis conversion sequences if(i>=arguments.size()) { // Ellipsis is the 'worst' of the conversion sequences distance+=1000; continue; } exprt argument=arguments[i]; exprt &operand=ops[i]; #if 0 // unclear, todo if(is_reference(operand.type())) std::cout << "O: " << operand.pretty() << std::endl; assert(!is_reference(operand.type())); #endif // "this" is a special case -- we turn the pointer type // into a reference type to do the type matching if(i==0 && argument.get("#base_name")==ID_this) { argument.type().set("#reference", true); argument.type().set("#this", true); } unsigned rank = 0; exprt new_expr; #if 0 std::cout << "C: " << cpp_typecheck.to_string(operand.type()) << " -> " << cpp_typecheck.to_string(argument.type()) << std::endl; #endif // can we do the standard conversion sequence? if(cpp_typecheck.implicit_conversion_sequence( operand, argument.type(), new_expr, rank)) { // ok distance+=rank; #if 0 std::cout << "OK " << rank << std::endl; #endif } else { #if 0 std::cout << "NOT OK" << std::endl; #endif return false; // no conversion possible } } return true; }