Esempio n. 1
0
bool remove_function_pointerst::is_type_compatible(
  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(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 arguments
  const code_typet::argumentst &call_arguments=call_type.arguments();
  const code_typet::argumentst &function_arguments=function_type.arguments();

  if(function_type.has_ellipsis() &&
     function_arguments.empty())
  {
    // always ok
  }
  else if(call_type.has_ellipsis() &&
          call_arguments.empty())
  {
    // always ok
  }
  else
  {
    // we are quite strict here, could be much more generous
    if(call_arguments.size()!=function_arguments.size())
      return false;
    
    for(unsigned i=0; i<call_arguments.size(); i++)
      if(!arg_is_type_compatible(call_arguments[i].type(),
                                 function_arguments[i].type()))
        return false;
  }
  
  return true;
}
Esempio n. 2
0
void cpp_typecheckt::convert_arguments(
  const irep_idt &mode,
  code_typet &function_type)
{
  code_typet::argumentst &arguments=
    function_type.arguments();

  for(code_typet::argumentst::iterator
      it=arguments.begin();
      it!=arguments.end();
      it++)
    convert_argument(mode, *it);
}
Esempio n. 3
0
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
  }
}
Esempio n. 4
0
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;
}