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 ¶meters=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 } } }
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; } }
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); }