コード例 #1
0
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;
}
コード例 #2
0
ファイル: cpp_typecheck_fargs.cpp プロジェクト: smaorus/rvt
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;
}