コード例 #1
0
void c_typecheck_baset::do_initializer(symbolt &symbol)
{
  // this one doesn't need initialization
  if(has_prefix(id2string(symbol.name), CPROVER_PREFIX "constant_infinity"))
    return;

  if(symbol.static_lifetime)
  {
    if(symbol.value.is_nil())
    {
      const typet &final_type=follow(symbol.type);
      
      if(final_type.id()!=ID_incomplete_struct &&
         final_type.id()!=ID_incomplete_array &&
         final_type.id()!=ID_empty)
      {
        // zero initializer
        symbol.value=zero_initializer(symbol.type, symbol.location);
        symbol.value.set("#zero_initializer", true);
      }
    }
    else
    {
      typecheck_expr(symbol.value);
      do_initializer(symbol.value, symbol.type, true);
      
      if(follow(symbol.type).id()==ID_incomplete_array)
        symbol.type=symbol.value.type();
    }
  }
  else if(!symbol.is_type)
  {
    const typet &final_type=follow(symbol.type);
    
    if(final_type.id()==ID_incomplete_c_enum ||
       final_type.id()==ID_c_enum)
    {
      if(symbol.is_macro)
      {
        // these must have a constant value
        assert(symbol.value.is_not_nil());
        typecheck_expr(symbol.value);
        locationt location=symbol.value.location();
        do_initializer(symbol.value, symbol.type, true);
        make_constant(symbol.value);
      }
    }
    else if(symbol.value.is_not_nil())
    {
      typecheck_expr(symbol.value);
      do_initializer(symbol.value, symbol.type, true);
      
      if(follow(symbol.type).id()==ID_incomplete_array)
        symbol.type=symbol.value.type();
    }
  }
}
コード例 #2
0
ファイル: c_typecheck_base.cpp プロジェクト: theyoucheng/cbmc
void c_typecheck_baset::typecheck_new_symbol(symbolt &symbol)
{
  if(symbol.is_parameter)
    adjust_function_parameter(symbol.type);

  // check initializer, if needed

  if(symbol.type.id()==ID_code)
  {
    if(symbol.value.is_not_nil() &&
       !symbol.is_macro)
      typecheck_function_body(symbol);
    else
    {
      // we don't need the identifiers
      code_typet &code_type=to_code_type(symbol.type);
      for(code_typet::parameterst::iterator
          it=code_type.parameters().begin();
          it!=code_type.parameters().end();
          it++)
        it->set_identifier(irep_idt());
    }
  }
  else
  {
    // check the initializer
    do_initializer(symbol);
  }
}
コード例 #3
0
void c_typecheck_baset::do_initializer(symbolt &symbol)
{
  // this one doesn't need initialization
  if(has_prefix(id2string(symbol.name), CPROVER_PREFIX "constant_infinity"))
    return;

  if(symbol.is_static_lifetime)
  {
    if(symbol.value.is_not_nil())
    {
      typecheck_expr(symbol.value);
      do_initializer(symbol.value, symbol.type, true);

      // need to adjust size?
      if(follow(symbol.type).id()==ID_array &&
         to_array_type(follow(symbol.type)).size().is_nil())
        symbol.type=symbol.value.type();
    }
  }
  else if(!symbol.is_type)
  {
    if(symbol.is_macro)
    {
      // these must have a constant value
      assert(symbol.value.is_not_nil());
      typecheck_expr(symbol.value);
      source_locationt location=symbol.value.source_location();
      do_initializer(symbol.value, symbol.type, true);
      make_constant(symbol.value);
    }
    else if(symbol.value.is_not_nil())
    {
      typecheck_expr(symbol.value);
      do_initializer(symbol.value, symbol.type, true);

      // need to adjust size?
      if(follow(symbol.type).id()==ID_array &&
         to_array_type(follow(symbol.type)).size().is_nil())
        symbol.type=symbol.value.type();
    }
  }
}
コード例 #4
0
ファイル: c_typecheck_base.cpp プロジェクト: Dthird/CBMC
void c_typecheck_baset::typecheck_new_symbol(symbolt &symbol)
{
  if(symbol.is_parameter)
    adjust_function_parameter(symbol.type);

  // check initializer, if needed

  if(symbol.type.id()==ID_code)
  {
    if(symbol.value.is_not_nil())
      typecheck_function_body(symbol);
    else
    {
      // we don't need the identifiers
      code_typet &code_type=to_code_type(symbol.type);
      for(code_typet::parameterst::iterator
          it=code_type.parameters().begin();
          it!=code_type.parameters().end();
          it++)
        it->set_identifier(irep_idt());
    }
  }
  else
  {
    if(symbol.type.id()==ID_array &&
       to_array_type(symbol.type).size().is_nil() &&
       !symbol.is_type)
    {
      // Insert a new type symbol for the array.
      // We do this because we want a convenient way
      // of adjusting the size of the type later on.

      type_symbolt new_symbol(symbol.type);
      new_symbol.name=id2string(symbol.name)+"$type";
      new_symbol.base_name=id2string(symbol.base_name)+"$type"; 
      new_symbol.location=symbol.location;
      new_symbol.mode=symbol.mode;
      new_symbol.module=symbol.module;
    
      symbol.type=symbol_typet(new_symbol.name);
    
      symbolt *new_sp;
      symbol_table.move(new_symbol, new_sp);
    }

    // check the initializer
    do_initializer(symbol);
  }
}
コード例 #5
0
ファイル: c_typecheck_base.cpp プロジェクト: Dthird/CBMC
void c_typecheck_baset::typecheck_redefinition_non_type(
  symbolt &old_symbol,
  symbolt &new_symbol)
{
  const typet &final_old=follow(old_symbol.type);
  const typet &initial_new=follow(new_symbol.type);

  if(final_old.id()==ID_array &&
     to_array_type(final_old).size().is_not_nil() &&
     initial_new.id()==ID_array &&
     to_array_type(initial_new).size().is_nil() &&
     final_old.subtype()==initial_new.subtype())
  {
    // this is ok, just use old type
    new_symbol.type=old_symbol.type;
  }

  // do initializer, this may change the type
  if(follow(new_symbol.type).id()!=ID_code)
    do_initializer(new_symbol);
  
  const typet &final_new=follow(new_symbol.type);
  
  // K&R stuff?
  if(old_symbol.type.id()==ID_KnR)
  {
    // check the type
    if(final_new.id()==ID_code)
    {
      err_location(new_symbol.location);
      throw "function type not allowed for K&R function parameter";
    }
    
    // fix up old symbol -- we now got the type
    old_symbol.type=new_symbol.type;
    return;
  }
  
  if(final_new.id()==ID_code)
  {
    bool inlined=
       (new_symbol.type.get_bool(ID_C_inlined) ||
        old_symbol.type.get_bool(ID_C_inlined));
        
    if(final_old.id()!=ID_code)
    {
      err_location(new_symbol.location);
      str << "error: function symbol `" << new_symbol.display_name()
          << "' redefined with a different type:" << "\n";
      str << "Original: " << to_string(old_symbol.type) << "\n";
      str << "     New: " << to_string(new_symbol.type);
      throw 0;
    }

    code_typet &old_ct=to_code_type(old_symbol.type);
    code_typet &new_ct=to_code_type(new_symbol.type);
    
    if(old_ct.has_ellipsis() && !new_ct.has_ellipsis())
      old_ct=new_ct;
    else if(!old_ct.has_ellipsis() && new_ct.has_ellipsis())
      new_ct=old_ct;

    if(inlined)
    {
      old_symbol.type.set(ID_C_inlined, true);
      new_symbol.type.set(ID_C_inlined, true);
    }

    // do body
    
    if(new_symbol.value.is_not_nil())
    {  
      if(old_symbol.value.is_not_nil())
      {
        // gcc allows re-definition if the first
        // definition is marked as "extern inline"
        
        if(old_symbol.type.get_bool(ID_C_inlined) &&
           (config.ansi_c.mode==configt::ansi_ct::flavourt::MODE_GCC_C ||
            config.ansi_c.mode==configt::ansi_ct::flavourt::MODE_ARM_C_CPP))
        {
          // overwrite "extern inline" properties
          old_symbol.is_extern=new_symbol.is_extern;
          old_symbol.is_file_local=new_symbol.is_file_local;

          // remove parameter declarations to avoid conflicts
          const code_typet::parameterst &old_p=old_ct.parameters();
          for(code_typet::parameterst::const_iterator
              p_it=old_p.begin();
              p_it!=old_p.end();
              p_it++)
          {
            const irep_idt &identifier=p_it->get_identifier();

            symbol_tablet::symbolst::iterator p_s_it=
              symbol_table.symbols.find(identifier);
            if(p_s_it!=symbol_table.symbols.end())
              symbol_table.symbols.erase(p_s_it);
          }
        }
        else
        {
          err_location(new_symbol.location);
          str << "function body `" << new_symbol.display_name()
              << "' defined twice";
          error_msg();
          throw 0;
        }
      }
      else if(inlined)
      {
        // preserve "extern inline" properties
        old_symbol.is_extern=new_symbol.is_extern;
        old_symbol.is_file_local=new_symbol.is_file_local;
      }

      typecheck_function_body(new_symbol);
    
      // overwrite location
      old_symbol.location=new_symbol.location;
    
      // move body
      old_symbol.value.swap(new_symbol.value);

      // overwrite type (because of parameter names)
      old_symbol.type=new_symbol.type;
    }

    return;
  }

  if(final_old!=final_new)
  {
    if(final_old.id()==ID_array &&
            to_array_type(final_old).size().is_nil() &&
            final_new.id()==ID_array &&
            to_array_type(final_new).size().is_not_nil() &&
            final_old.subtype()==final_new.subtype())
    {
      // this is also ok
      if(old_symbol.type.id()==ID_symbol)
      {
        // fix the symbol, not just the type
        const irep_idt identifier=
          to_symbol_type(old_symbol.type).get_identifier();

        symbol_tablet::symbolst::iterator s_it=symbol_table.symbols.find(identifier);
  
        if(s_it==symbol_table.symbols.end())
        {
          err_location(old_symbol.location);
          str << "typecheck_redefinition_non_type: "
                 "failed to find symbol `" << identifier << "'";
          throw 0;
        }
                  
        symbolt &symbol=s_it->second;
          
        symbol.type=final_new;          
      }
      else
        old_symbol.type=new_symbol.type;
    }
    else if((final_old.id()==ID_incomplete_c_enum ||
             final_old.id()==ID_c_enum) &&
            (final_new.id()==ID_incomplete_c_enum ||
             final_new.id()==ID_c_enum))
    {
      // this is ok for now
    }
    else if(final_old.id()==ID_pointer &&
            follow(final_old).subtype().id()==ID_code &&
            to_code_type(follow(final_old).subtype()).has_ellipsis() &&
            final_new.id()==ID_pointer &&
            follow(final_new).subtype().id()==ID_code)
    {
      // to allow 
      // int (*f) ();
      // int (*f) (int)=0;
      old_symbol.type=new_symbol.type;
    }
    else if(final_old.id()==ID_pointer &&
            follow(final_old).subtype().id()==ID_code &&
            final_new.id()==ID_pointer &&
            follow(final_new).subtype().id()==ID_code &&
            to_code_type(follow(final_new).subtype()).has_ellipsis())
    {
      // to allow 
      // int (*f) (int)=0;
      // int (*f) ();
    }
    else
    {
      err_location(new_symbol.location);
      str << "error: symbol `" << new_symbol.display_name()
          << "' redefined with a different type:" << "\n";
      str << "Original: " << to_string(old_symbol.type) << "\n";
      str << "     New: " << to_string(new_symbol.type);
      throw 0;
    }
  }
  else // finals are equal
  {
  }

  // do value
  if(new_symbol.value.is_not_nil())
  {
    // see if we already have one
    if(old_symbol.value.is_not_nil())
    {
      if(new_symbol.value.get_bool(ID_C_zero_initializer))
      {
        // do nothing
      }
      else if(old_symbol.value.get_bool(ID_C_zero_initializer))
      {
        old_symbol.value=new_symbol.value;
        old_symbol.type=new_symbol.type;
      }
      else
      {
        if(new_symbol.is_macro &&
           (final_new.id()==ID_incomplete_c_enum ||
            final_new.id()==ID_c_enum) &&
            old_symbol.value.is_constant() &&
            new_symbol.value.is_constant() &&
            old_symbol.value.get(ID_value)==new_symbol.value.get(ID_value))
        {
          // ignore
        }
        else
        {
          err_location(new_symbol.value);
          str << "symbol `" << new_symbol.display_name()
              << "' already has an initial value";
          warning_msg();
        }
      }
    }
    else
    {
      old_symbol.value=new_symbol.value;
      old_symbol.type=new_symbol.type;
    }
  }
  
  // take care of some flags
  if(old_symbol.is_extern && !new_symbol.is_extern)
    old_symbol.location=new_symbol.location;

  old_symbol.is_extern=old_symbol.is_extern && new_symbol.is_extern;
  
  // We should likely check is_volatile and
  // is_thread_local for consistency. GCC complains if these
  // mismatch.
}