示例#1
0
  Forall_goto_program_instructions(i_it, goto_program)
  {
    if(i_it->is_function_call())
    {
      code_function_callt &function_call=to_code_function_call(i_it->code);

      code_typet old_type=to_code_type(function_call.function().type());

      // Do we return anything?
      if(old_type.return_type()!=empty_typet())
      {
        // replace "lhs=f(...)" by "f(...); lhs=f#return_value; DEAD f#return_value;"
        assert(function_call.function().id()==ID_symbol);

        const irep_idt function_id=
          to_symbol_expr(function_call.function()).get_identifier();

        // see if we have a body
        goto_functionst::function_mapt::const_iterator
          f_it=goto_functions.function_map.find(function_id);

        if(f_it==goto_functions.function_map.end())
          throw "failed to find function `"+id2string(function_id)+"' in function map";

        // fix the type
        to_code_type(function_call.function().type()).return_type()=empty_typet();

        if(function_call.lhs().is_not_nil())
        {
          exprt rhs;
          
          symbol_exprt return_value;
          return_value.type()=function_call.lhs().type();
          return_value.set_identifier(id2string(function_id)+RETURN_VALUE_SUFFIX);
          rhs=return_value;

          goto_programt::targett t_a=goto_program.insert_after(i_it);
          t_a->make_assignment();
          t_a->source_location=i_it->source_location;
          t_a->code=code_assignt(function_call.lhs(), rhs);
          t_a->function=i_it->function;

          // fry the previous assignment
          function_call.lhs().make_nil();

          if(f_it->second.body_available())
          {
            goto_programt::targett t_d=goto_program.insert_after(t_a);
            t_d->make_dead();
            t_d->source_location=i_it->source_location;
            t_d->code=code_deadt(rhs);
            t_d->function=i_it->function;
          }
        }
      }
    }
  }
void java_internal_additions(symbol_tablet &dest)
{
  // add __CPROVER_rounding_mode

  {
    symbolt symbol;
    symbol.base_name="__CPROVER_rounding_mode";
    symbol.name=CPROVER_PREFIX "rounding_mode";
    symbol.type=signed_int_type();
    symbol.mode=ID_C;
    symbol.is_lvalue=true;
    symbol.is_state_var=true;
    symbol.is_thread_local=true;
    dest.add(symbol);
  }

  // add __CPROVER_malloc_object

  {
    symbolt symbol;
    symbol.base_name="__CPROVER_malloc_object";
    symbol.name=CPROVER_PREFIX "malloc_object";
    symbol.type=pointer_type(empty_typet());
    symbol.mode=ID_C;
    symbol.is_lvalue=true;
    symbol.is_state_var=true;
    symbol.is_thread_local=true;
    dest.add(symbol);
  }
}
示例#3
0
void thread_exit_instrumentation(goto_programt &goto_program)
{
  if(goto_program.instructions.empty()) return;

  // add assertion that all may flags for mutex-locked are gone
  // at the end
  goto_programt::targett end=goto_program.instructions.end();
  end--;

  assert(end->is_end_function());

  source_locationt source_location=end->source_location;
  irep_idt function=end->function;

  goto_program.insert_before_swap(end);

  exprt mutex_locked_string=
    string_constantt("mutex-locked");

  binary_exprt get_may("get_may");

  // NULL is any
  get_may.op0()=constant_exprt(ID_NULL, pointer_typet(empty_typet()));
  get_may.op1()=address_of_exprt(mutex_locked_string);

  end->make_assertion(not_exprt(get_may));

  end->source_location=source_location;
  end->source_location.set_comment("mutexes must not be locked on thread exit");
  end->function=function;
}
示例#4
0
static void create_initialize(symbol_tablet &symbol_table)
{
  symbolt initialize;
  initialize.name=INITIALIZE;
  initialize.base_name=INITIALIZE;
  initialize.mode=ID_java;

  code_typet type;
  type.return_type()=empty_typet();
  initialize.type=type;

  code_blockt init_code;

  namespacet ns(symbol_table);

  symbol_exprt rounding_mode=
    ns.lookup(CPROVER_PREFIX "rounding_mode").symbol_expr();

  init_code.add(
    code_assignt(rounding_mode, from_integer(0, rounding_mode.type())));

  initialize.value=init_code;

  if(symbol_table.add(initialize))
    throw "failed to add "+std::string(INITIALIZE);
}
示例#5
0
code_function_callt function_to_call(
  symbol_tablet &symbol_table,
  const irep_idt &id,
  const irep_idt &argument)
{
  // already there?

  symbol_tablet::symbolst::const_iterator s_it=
    symbol_table.symbols.find(id);

  if(s_it==symbol_table.symbols.end())
  {
    // not there
    pointer_typet p(char_type());
    p.subtype().set(ID_C_constant, true);

    code_typet function_type;
    function_type.return_type()=empty_typet();
    function_type.parameters().push_back(
      code_typet::parametert(p));

    symbolt new_symbol;
    new_symbol.name=id;
    new_symbol.base_name=id;
    new_symbol.type=function_type;

    symbol_table.move(new_symbol);

    s_it=symbol_table.symbols.find(id);
    assert(s_it!=symbol_table.symbols.end());
  }

  // signature is expected to be
  // (type *) -> ...
  if(s_it->second.type.id()!=ID_code ||
     to_code_type(s_it->second.type).parameters().size()!=1 ||
     to_code_type(s_it->second.type).parameters()[0].type().id()!=ID_pointer)
  {
    std::string error="function `"+id2string(id)+"' has wrong signature";
    throw error;
  }

  string_constantt function_id_string(argument);

  code_function_callt call;
  call.lhs().make_nil();
  call.function()=
    symbol_exprt(s_it->second.name, s_it->second.type);
  call.arguments().resize(1);
  call.arguments()[0]=
    typecast_exprt(
      address_of_exprt(
        index_exprt(
          function_id_string, from_integer(0, index_type()))),
      to_code_type(s_it->second.type).parameters()[0].type());

  return call;
}
示例#6
0
void java_record_outputs(
  const symbolt &function,
  const exprt::operandst &main_arguments,
  code_blockt &init_code,
  symbol_tablet &symbol_table)
{
  const code_typet::parameterst &parameters=
    to_code_type(function.type).parameters();

  exprt::operandst result;
  result.reserve(parameters.size()+1);

  bool has_return_value=
    to_code_type(function.type).return_type()!=empty_typet();

  if(has_return_value)
  {
    // record return value
    codet output(ID_output);
    output.operands().resize(2);

    const symbolt &return_symbol=symbol_table.lookup("return'");

    output.op0()=
      address_of_exprt(
        index_exprt(
          string_constantt(return_symbol.base_name),
          from_integer(0, index_type())));
    output.op1()=return_symbol.symbol_expr();
    output.add_source_location()=function.location;

    init_code.move_to_operands(output);
  }

  for(std::size_t param_number=0;
      param_number<parameters.size();
      param_number++)
  {
    const symbolt &p_symbol=
      symbol_table.lookup(parameters[param_number].get_identifier());

    if(p_symbol.type.id()==ID_pointer)
    {
      // record as an output
      codet output(ID_output);
      output.operands().resize(2);
      output.op0()=
        address_of_exprt(
          index_exprt(
            string_constantt(p_symbol.base_name),
            from_integer(0, index_type())));
      output.op1()=main_arguments[param_number];
      output.add_source_location()=function.location;

      init_code.move_to_operands(output);
    }
  }
}
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;
}
示例#8
0
void c_typecheck_baset::typecheck_gcc_computed_goto(codet &code)
{
  if(code.operands().size()!=1)
  {
    err_location(code);
    error() << "computed-goto expected to have one operand" << eom;
    throw 0;
  }

  exprt &dest=code.op0();

  if(dest.id()!=ID_dereference)
  {
    err_location(dest);
    error() << "computed-goto expected to have dereferencing operand"
            << eom;
    throw 0;
  }

  assert(dest.operands().size()==1);

  typecheck_expr(dest.op0());
  dest.type()=empty_typet();
}
示例#9
0
bool java_entry_point(
  symbol_tablet &symbol_table,
  const irep_idt &main_class,
  message_handlert &message_handler)
{
  // check if the entry point is already there
  if(symbol_table.symbols.find(goto_functionst::entry_point())!=
     symbol_table.symbols.end())
    return false; // silently ignore

  messaget message(message_handler);

  symbolt symbol; // main function symbol

  // find main symbol
  if(config.main!="")
  {
    // Add java:: prefix
    std::string main_identifier="java::"+config.main;
    
    symbol_tablet::symbolst::const_iterator s_it;
    
    // Does it have a type signature? (':' suffix)
    if(config.main.rfind(':')==std::string::npos)
    {
      std::string prefix=main_identifier+':';
      std::set<irep_idt> matches;
      
      for(const auto & s : symbol_table.symbols)
        if(has_prefix(id2string(s.first), prefix) &&
           s.second.type.id()==ID_code)
          matches.insert(s.first);

      if(matches.empty())
      {
        message.error() << "main symbol `" << config.main
                        << "' not found" << messaget::eom;
        return true;
      }
      else if(matches.size()==1)
      {
        s_it=symbol_table.symbols.find(*matches.begin());
        assert(s_it!=symbol_table.symbols.end());
      }
      else
      {
        message.error() << "main symbol `" << config.main
                        << "' is ambiguous:\n";

        for(const auto & s : matches)
          message.error() << "  " << s << '\n';
        
        message.error() << messaget::eom;

        return true;
      }
    }
    else
    {
      // just look it up
      s_it=symbol_table.symbols.find(main_identifier);

      if(s_it==symbol_table.symbols.end())
      {
        message.error() << "main symbol `" << config.main
                        << "' not found" << messaget::eom;
        return true;
      }
    }

    // function symbol
    symbol=s_it->second;

    if(symbol.type.id()!=ID_code)
    {
      message.error() << "main symbol `" << config.main
                      << "' not a function" << messaget::eom;
      return true;
    }
    
    // check if it has a body
    if(symbol.value.is_nil())
    {
      message.error() << "main method `" << main_class
                      << "' has no body" << messaget::eom;
      return true;
    }
  }
  else
  {
    // no function given, we look for the main class
    assert(config.main=="");

    // are we given a main class?
    if(main_class.empty())
      return false; // silently ignore

    std::string entry_method=
      id2string(main_class)+".main";

    std::string prefix="java::"+entry_method+":";

    // look it up
    std::set<irep_idt> matches;

    for(symbol_tablet::symbolst::const_iterator
        s_it=symbol_table.symbols.begin();
        s_it!=symbol_table.symbols.end();
        s_it++)
    {
      if(s_it->second.type.id()==ID_code &&
         has_prefix(id2string(s_it->first), prefix))
        matches.insert(s_it->first);
    }

    if(matches.empty())
    {
      // Not found, silently ignore
      return false;
    }

    if(matches.size()>=2)
    {
      message.error() << "main method in `" << main_class
                      << "' is ambiguous" << messaget::eom;
      return true; // give up with error, no main
    }

    // function symbol
    symbol=symbol_table.symbols.find(*matches.begin())->second;
  
    // check if it has a body
    if(symbol.value.is_nil())
    {
      message.error() << "main method `" << main_class
                      << "' has no body" << messaget::eom;
      return true; // give up with error
    }
  }

  assert(!symbol.value.is_nil());
  assert(symbol.type.id()==ID_code);

  const code_typet &code_type=to_code_type(symbol.type);
    
  create_initialize(symbol_table);

  if(java_static_lifetime_init(symbol_table, symbol.location, message_handler))
    return true;

  code_blockt init_code;

  // build call to initialization function
  {
    symbol_tablet::symbolst::iterator init_it=
      symbol_table.symbols.find(INITIALIZE);

    if(init_it==symbol_table.symbols.end())
    {
      message.error() << "failed to find " INITIALIZE " symbol"
                      << messaget::eom;
      return true; // give up with error
    }

    code_function_callt call_init;
    call_init.lhs().make_nil();
    call_init.add_source_location()=symbol.location;
    call_init.function()=init_it->second.symbol_expr();

    init_code.move_to_operands(call_init);
  }

  // build call to the main method

  code_function_callt call_main;
  call_main.add_source_location()=symbol.location;
  call_main.function()=symbol.symbol_expr();

  const code_typet::parameterst &parameters=
    code_type.parameters();

  exprt::operandst main_arguments;
  main_arguments.resize(parameters.size());
  
  for(std::size_t param_number=0;
      param_number<parameters.size();
      param_number++)
  {
    bool is_this=param_number==0 &&
                 parameters[param_number].get_this();
    bool allow_null=config.main!="" && !is_this;
    
    main_arguments[param_number]=
      object_factory(parameters[param_number].type(), 
                     init_code, allow_null, symbol_table);
  }

  call_main.arguments()=main_arguments;

  init_code.move_to_operands(call_main);

  // add "main"
  symbolt new_symbol;

  code_typet main_type;
  main_type.return_type()=empty_typet();

  new_symbol.name=goto_functionst::entry_point();
  new_symbol.type.swap(main_type);
  new_symbol.value.swap(init_code);
  new_symbol.mode=ID_java;

  if(symbol_table.move(new_symbol))
  {
    message.error() << "failed to move main symbol" << messaget::eom;
    return true;
  }

  return false;
}
示例#10
0
typet void_type()
{
  return empty_typet();
}
示例#11
0
void cpp_typecheckt::convert_function(symbolt &symbol)
{
  code_typet &function_type=
    to_code_type(template_subtype(symbol.type));

  // only a prototype?
  if(symbol.value.is_nil())
    return;

  // if it is a destructor, add the implicit code
  if(symbol.type.get(ID_return_type)==ID_destructor)
  {
    const symbolt &msymb=lookup(symbol.type.get(ID_C_member_name));

    assert(symbol.value.id()==ID_code);
    assert(symbol.value.get(ID_statement)==ID_block);

    symbol.value.copy_to_operands(dtor(msymb));
  }

  // enter appropriate scope
  cpp_save_scopet saved_scope(cpp_scopes);
  cpp_scopet &function_scope=cpp_scopes.set_scope(symbol.name);

  // fix the scope's prefix
  function_scope.prefix+=id2string(symbol.name)+"::";

  // genuine function definition -- do the parameter declarations
  convert_arguments(symbol.mode, function_type);

  // create "this" if it's a non-static method
  if(function_scope.is_method &&
     !function_scope.is_static_member)
  {
    code_typet::argumentst &arguments=function_type.arguments();
    assert(arguments.size()>=1);
    code_typet::argumentt &this_argument_expr=arguments.front();
    function_scope.this_expr=exprt(ID_symbol, this_argument_expr.type());
    function_scope.this_expr.set(ID_identifier, this_argument_expr.get(ID_C_identifier));
  }
  else
    function_scope.this_expr.make_nil();

  // do the function body
  start_typecheck_code();

  // save current return type
  typet old_return_type=return_type;

  return_type=function_type.return_type();

  // constructor, destructor?
  if(return_type.id()==ID_constructor ||
     return_type.id()==ID_destructor)
    return_type=empty_typet();
  
  typecheck_code(to_code(symbol.value));

  symbol.value.type()=symbol.type;
  
  return_type = old_return_type;
}
示例#12
0
文件: bp_language.cpp 项目: olivo/BP
  Inputs:

 Outputs:

 Purpose:

\*******************************************************************/

bool bp_languaget::final(
  contextt &context,
  message_handlert &message_handler)
{
  // do main symbol
  
  code_typet main_type;
  main_type.return_type()=empty_typet();
  
  symbolt new_symbol;
  new_symbol.name="main";
  new_symbol.type=main_type;
  
  const contextt::symbolst::const_iterator s_it=
    context.symbols.find("bp::fkt::main");
    
  if(s_it==context.symbols.end())
    return false;
    
  const symbolt &symbol=s_it->second;

  code_function_callt call;
  call.function()=symbol_expr(symbol);
示例#13
0
/// turns 'return x' into an assignment to fkt#return_value
void remove_returnst::replace_returns(
  goto_functionst::function_mapt::iterator f_it)
{
  typet return_type=f_it->second.type.return_type();

  const irep_idt function_id=f_it->first;

  // returns something but void?
  bool has_return_value=return_type!=empty_typet();

  if(has_return_value)
  {
    // look up the function symbol
    symbol_tablet::symbolst::iterator s_it=
      symbol_table.symbols.find(function_id);

    assert(s_it!=symbol_table.symbols.end());
    symbolt &function_symbol=s_it->second;

    // make the return type 'void'
    f_it->second.type.return_type()=empty_typet();
    function_symbol.type=f_it->second.type;

    // add return_value symbol to symbol_table
    auxiliary_symbolt new_symbol;
    new_symbol.is_static_lifetime=true;
    new_symbol.module=function_symbol.module;
    new_symbol.base_name=
      id2string(function_symbol.base_name)+RETURN_VALUE_SUFFIX;
    new_symbol.name=id2string(function_symbol.name)+RETURN_VALUE_SUFFIX;
    new_symbol.mode=function_symbol.mode;
    new_symbol.type=return_type;

    symbol_table.add(new_symbol);
  }

  goto_programt &goto_program=f_it->second.body;

  if(goto_program.empty())
    return;

  if(has_return_value)
  {
    Forall_goto_program_instructions(i_it, goto_program)
    {
      if(i_it->is_return())
      {
        assert(i_it->code.operands().size()==1);

        // replace "return x;" by "fkt#return_value=x;"
        symbol_exprt lhs_expr;
        lhs_expr.set_identifier(id2string(function_id)+RETURN_VALUE_SUFFIX);
        lhs_expr.type()=return_type;

        code_assignt assignment(lhs_expr, i_it->code.op0());

        // now turn the `return' into `assignment'
        i_it->type=ASSIGN;
        i_it->code=assignment;
      }
    }
  }
}
示例#14
0
bool java_static_lifetime_init(
  symbol_tablet &symbol_table,
  const source_locationt &source_location,
  message_handlert &message_handler,
  bool assume_init_pointers_not_null,
  unsigned max_nondet_array_length)
{
  symbolt &initialize_symbol=symbol_table.lookup(INITIALIZE);
  code_blockt &code_block=to_code_block(to_code(initialize_symbol.value));

  // We need to zero out all static variables, or nondet-initialize if they're
  // external. Iterate over a copy of the symtab, as its iterators are
  // invalidated by object_factory:

  std::list<irep_idt> symbol_names;
  for(const auto &entry : symbol_table.symbols)
    symbol_names.push_back(entry.first);

  for(const auto &symname : symbol_names)
  {
    const symbolt &sym=symbol_table.lookup(symname);
    if(should_init_symbol(sym))
    {
      if(sym.value.is_nil() && sym.type!=empty_typet())
      {
        bool allow_null=!assume_init_pointers_not_null;
        if(allow_null)
        {
          std::string namestr=id2string(sym.symbol_expr().get_identifier());
          const std::string suffix="@class_model";
          // Static '.class' fields are always non-null.
          if(has_suffix(namestr, suffix))
            allow_null=false;
          if(allow_null && has_prefix(
               namestr,
               "java::java.lang.String.Literal"))
            allow_null=false;
        }
        auto newsym=object_factory(
          sym.type,
          code_block,
          allow_null,
          symbol_table,
          max_nondet_array_length,
          source_location,
          message_handler);
        code_assignt assignment(sym.symbol_expr(), newsym);
        code_block.add(assignment);
      }
      else if(sym.value.is_not_nil())
      {
        code_assignt assignment(sym.symbol_expr(), sym.value);
        assignment.add_source_location()=source_location;
        code_block.add(assignment);
      }
    }
  }

  // we now need to run all the <clinit> methods

  for(symbol_tablet::symbolst::const_iterator
      it=symbol_table.symbols.begin();
      it!=symbol_table.symbols.end();
      it++)
  {
    if(it->second.base_name=="<clinit>" &&
       it->second.type.id()==ID_code &&
       it->second.mode==ID_java)
    {
      code_function_callt function_call;
      function_call.lhs()=nil_exprt();
      function_call.function()=it->second.symbol_expr();
      function_call.add_source_location()=source_location;
      code_block.add(function_call);
    }
  }

  return false;
}
示例#15
0
bool java_entry_point(
  symbol_tablet &symbol_table,
  const irep_idt &main_class,
  message_handlert &message_handler,
  bool assume_init_pointers_not_null,
  size_t max_nondet_array_length)
{
  // check if the entry point is already there
  if(symbol_table.symbols.find(goto_functionst::entry_point())!=
     symbol_table.symbols.end())
    return false; // silently ignore

  messaget message(message_handler);
  main_function_resultt res=
    get_main_symbol(symbol_table, main_class, message_handler);
  if(res.stop_convert)
    return res.stop_convert;
  symbolt symbol=res.main_function;

  assert(!symbol.value.is_nil());
  assert(symbol.type.id()==ID_code);

  create_initialize(symbol_table);

  if(java_static_lifetime_init(
       symbol_table,
       symbol.location,
       message_handler,
       assume_init_pointers_not_null,
       max_nondet_array_length))
    return true;

  code_blockt init_code;

  // build call to initialization function
  {
    symbol_tablet::symbolst::iterator init_it=
      symbol_table.symbols.find(INITIALIZE);

    if(init_it==symbol_table.symbols.end())
    {
      message.error() << "failed to find " INITIALIZE " symbol"
                      << messaget::eom;
      return true; // give up with error
    }

    code_function_callt call_init;
    call_init.lhs().make_nil();
    call_init.add_source_location()=symbol.location;
    call_init.function()=init_it->second.symbol_expr();

    init_code.move_to_operands(call_init);
  }

  // build call to the main method

  code_function_callt call_main;

  source_locationt loc=symbol.location;
  loc.set_function(symbol.name);
  source_locationt &dloc=loc;

  call_main.add_source_location()=dloc;
  call_main.function()=symbol.symbol_expr();
  call_main.function().add_source_location()=dloc;

  if(to_code_type(symbol.type).return_type()!=empty_typet())
  {
    auxiliary_symbolt return_symbol;
    return_symbol.mode=ID_C;
    return_symbol.is_static_lifetime=false;
    return_symbol.name="return'";
    return_symbol.base_name="return";
    return_symbol.type=to_code_type(symbol.type).return_type();

    symbol_table.add(return_symbol);
    call_main.lhs()=return_symbol.symbol_expr();
  }

  exprt::operandst main_arguments=
    java_build_arguments(
      symbol,
      init_code,
      symbol_table,
      assume_init_pointers_not_null,
      max_nondet_array_length,
      message_handler);
  call_main.arguments()=main_arguments;

  init_code.move_to_operands(call_main);

  java_record_outputs(symbol, main_arguments, init_code, symbol_table);

  // add "main"
  symbolt new_symbol;

  code_typet main_type;
  main_type.return_type()=empty_typet();

  new_symbol.name=goto_functionst::entry_point();
  new_symbol.type.swap(main_type);
  new_symbol.value.swap(init_code);
  new_symbol.mode=ID_java;

  if(symbol_table.move(new_symbol))
  {
    message.error() << "failed to move main symbol" << messaget::eom;
    return true;
  }

  return false;
}
示例#16
0
void c_typecheck_baset::typecheck_declaration(
  ansi_c_declarationt &declaration)
{
  if(declaration.get_is_static_assert())
  {
    assert(declaration.operands().size()==2);
    typecheck_expr(declaration.op0());
    typecheck_expr(declaration.op1());
  }
  else
  {
    // get storage spec
    c_storage_spect c_storage_spec(declaration.type());

    // first typecheck the type of the declaration
    typecheck_type(declaration.type());

    // mark as 'already typechecked'
    make_already_typechecked(declaration.type());

    codet contract;

    {
      exprt spec_requires=
        static_cast<const exprt&>(declaration.find(ID_C_spec_requires));
      contract.add(ID_C_spec_requires).swap(spec_requires);

      exprt spec_ensures=
        static_cast<const exprt&>(declaration.find(ID_C_spec_ensures));
      contract.add(ID_C_spec_ensures).swap(spec_ensures);
    }

    // Now do declarators, if any.
    for(ansi_c_declarationt::declaratorst::iterator
        d_it=declaration.declarators().begin();
        d_it!=declaration.declarators().end();
        d_it++)
    {
      c_storage_spect full_spec(declaration.full_type(*d_it));
      full_spec|=c_storage_spec;

      declaration.set_is_inline(full_spec.is_inline);
      declaration.set_is_static(full_spec.is_static);
      declaration.set_is_extern(full_spec.is_extern);
      declaration.set_is_thread_local(full_spec.is_thread_local);
      declaration.set_is_register(full_spec.is_register);
      declaration.set_is_typedef(full_spec.is_typedef);
      declaration.set_is_weak(full_spec.is_weak);

      symbolt symbol;
      declaration.to_symbol(*d_it, symbol);
      current_symbol=symbol;

      // now check other half of type
      typecheck_type(symbol.type);

      if(!full_spec.alias.empty())
      {
        if(symbol.value.is_not_nil())
        {
          error().source_location=symbol.location;
          error() << "alias attribute cannot be used with a body"
                  << eom;
          throw 0;
        }

        // alias function need not have been declared yet, thus
        // can't lookup
        symbol.value=symbol_exprt(full_spec.alias);
        symbol.is_macro=true;
      }

      if(full_spec.section.empty())
        apply_asm_label(full_spec.asm_label, symbol);
      else
      {
        std::string asm_name;
        asm_name=id2string(full_spec.section)+"$$";
        if(!full_spec.asm_label.empty())
          asm_name+=id2string(full_spec.asm_label);
        else
          asm_name+=id2string(symbol.name);

        apply_asm_label(asm_name, symbol);
      }
      irep_idt identifier=symbol.name;
      d_it->set_name(identifier);

      typecheck_symbol(symbol);

      // add code contract (if any); we typecheck this after the
      // function body done above, so as to have parameter symbols
      // available
      symbol_tablet::symbolst::iterator s_it=
        symbol_table.symbols.find(identifier);
      assert(s_it!=symbol_table.symbols.end());
      symbolt &new_symbol=s_it->second;

      typecheck_spec_expr(contract, ID_C_spec_requires);

      typet ret_type=empty_typet();
      if(new_symbol.type.id()==ID_code)
        ret_type=to_code_type(new_symbol.type).return_type();
      assert(parameter_map.empty());
      if(ret_type.id()!=ID_empty)
        parameter_map["__CPROVER_return_value"]=ret_type;
      typecheck_spec_expr(contract, ID_C_spec_ensures);
      parameter_map.clear();

      if(contract.find(ID_C_spec_requires).is_not_nil())
        new_symbol.type.add(ID_C_spec_requires)=
          contract.find(ID_C_spec_requires);
      if(contract.find(ID_C_spec_ensures).is_not_nil())
        new_symbol.type.add(ID_C_spec_ensures)=
          contract.find(ID_C_spec_ensures);
    }
  }
}