void get_symbols_rec(
  const namespacet &ns,
  const symbolt &symbol,
  find_symbols_sett &dest)
{
  dest.insert(symbol.name);
  
  find_symbols_sett new_symbols;

  find_type_and_expr_symbols(symbol.type, new_symbols);
  find_type_and_expr_symbols(symbol.value, new_symbols);
  
  if(symbol.type.id()==ID_code)
  {
    const code_typet &code_type=to_code_type(symbol.type);
    const code_typet::parameterst &parameters=code_type.parameters();

    for(code_typet::parameterst::const_iterator
        it=parameters.begin();
        it!=parameters.end();
        it++)
    {
      irep_idt id=it->get_identifier();
      const symbolt *s;
      // identifiers for prototypes need not exist
      if(!ns.lookup(id, s)) new_symbols.insert(id);
    }
  }

  for(find_symbols_sett::const_iterator
      it=new_symbols.begin();
      it!=new_symbols.end();
      it++)
  {
    if(dest.find(*it)==dest.end())
    {
      dest.insert(*it);
      get_symbols_rec(ns, ns.lookup(*it), dest); // recursive call
    }
  }
}
Example #2
0
void linkingt::duplicate_type_symbol(
  symbolt &old_symbol,
  symbolt &new_symbol,
  bool &move)
{
  // check if it is really the same
  // -- use base_type_eq, not linking_type_eq
  // first make sure that base_type_eq can soundly use ns/main_context only
  find_symbols_sett symbols;
  find_type_and_expr_symbols(new_symbol.type, symbols);
  bool ok=true;
  for(find_symbols_sett::const_iterator
      s_it=symbols.begin();
      ok && s_it!=symbols.end();
      s_it++)
    ok&=completed.find(*s_it)!=completed.end();
  if(ok && base_type_eq(old_symbol.type, new_symbol.type, ns))
  {
    move=false;
    return;
  }

  // they are different
  if(old_symbol.type.id()==ID_incomplete_struct &&
     new_symbol.type.id()==ID_struct)
  {
    if(move)
      old_symbol.type=new_symbol.type; // store new type
    move=false;
  }
  else if(old_symbol.type.id()==ID_struct &&
          new_symbol.type.id()==ID_incomplete_struct)
  {
    // ignore
    move=false;
  }
  else if(ns.follow(old_symbol.type).id()==ID_array &&
          ns.follow(new_symbol.type).id()==ID_array)
  {
    if(move &&
       to_array_type(ns.follow(old_symbol.type)).size().is_nil() &&
       to_array_type(ns.follow(new_symbol.type)).size().is_not_nil())
      old_symbol.type=new_symbol.type; // store new type
    move=false;
  }
  else
  {
    if(move)
      rename_type_symbol(new_symbol);
    move=true;
  }
}
Example #3
0
void linkingt::inspect_src_symbol(const irep_idt &identifier)
{
  // is it done already?
  if(completed.find(identifier)!=completed.end())
    return;

  // look it up, it must be there
  symbolt &new_symbol=src_context.lookup(identifier);

  // resolve recursion on types; we shouldn't need specific care
  // for non-types even though recursion may occur via initializers
  if(!processing.insert(identifier).second)
  {
    if(!main_context.has_symbol(identifier))
      return;

    symbolt &old_symbol=main_context.lookup(identifier);
    bool move=false;
    if(new_symbol.is_type && old_symbol.is_type)
      duplicate_type_symbol(old_symbol, new_symbol, move);

    if(move)
    {
      irep_idt old_identifier=new_symbol.name;
      irep_idt new_identifier=rename(old_identifier);

      replace_symbol.insert(old_identifier, symbol_typet(new_identifier));
    }

    return;
  }

  // first find out what symbols this uses
  find_symbols_sett symbols;
  find_type_and_expr_symbols(new_symbol.value, symbols);
  find_type_and_expr_symbols(new_symbol.type, symbols);
  // also add function arguments
  if(new_symbol.type.id()==ID_code)
  {
    const code_typet &code_type=to_code_type(new_symbol.type);
    const code_typet::argumentst &arguments=code_type.arguments();

    for(code_typet::argumentst::const_iterator
        it=arguments.begin();
        it!=arguments.end();
        it++)
      // identifiers for prototypes need not exist
      if(!it->get_identifier().empty() &&
          src_context.has_symbol(it->get_identifier()))
        symbols.insert(it->get_identifier());
  }

  // make sure we inspect those first!
  for(find_symbols_sett::const_iterator
      s_it=symbols.begin();
      s_it!=symbols.end();
      s_it++)
    inspect_src_symbol(*s_it);
    
  // first order of business is to apply renaming
  replace_symbol.replace(new_symbol.value);
  replace_symbol.replace(new_symbol.type);        
  // also rename function arguments, if necessary
  if(new_symbol.type.id()==ID_code)
  {
    code_typet &code_type=to_code_type(new_symbol.type);
    code_typet::argumentst &arguments=code_type.arguments();

    for(code_typet::argumentst::iterator
        it=arguments.begin();
        it!=arguments.end();
        it++)
    {
      replace_symbolt::expr_mapt::const_iterator r=
        replace_symbol.expr_map.find(it->get_identifier());
      if(r!=replace_symbol.expr_map.end())
        it->set_identifier(to_symbol_expr(r->second).get_identifier());
    }
  }
    
  // any symbols contained in new_symbol are now renamed within src_context and
  // the (possibly renamed) contained symbols are in main_context
  // any checks for duplicates are now safe to exclusively use lookups on
  // main_context (via ns)

  // ok, now check if we are to expect a collision
  const contextt::symbolst::iterator main_s_it=
    main_context.symbols.find(identifier);
    
  if(main_s_it!=main_context.symbols.end())
    duplicate_symbol(main_s_it->second, new_symbol); // handle the collision
  else
  {
    // add into destination context -- should never fail,
    // as there is no collision
    
    bool result=main_context.move(new_symbol);
    assert(!result);    
  }

  // symbol is really done and can now be used within main_context
  completed.insert(identifier);
  processing.erase(identifier);
}