void cpp_declarator_convertert::handle_initializer( symbolt &symbol, cpp_declaratort &declarator) { exprt &value=declarator.value(); // moves member initializers into 'value' cpp_typecheck.move_member_initializers( declarator.member_initializers(), symbol.type, value); // any initializer to be done? if(value.is_nil()) return; if(symbol.is_extern) { // the symbol is really located here symbol.is_extern=false; } if(symbol.value.is_nil()) { // no initial value yet symbol.value.swap(value); if(is_code && declarator.type().id()!=ID_template) cpp_typecheck.add_function_body(&symbol); if(!is_code) cpp_typecheck.convert_initializer(symbol); } else { #if 0 cpp_typecheck.err_location(declarator.name()); if(is_code) cpp_typecheck.str << "body of function `" << symbol.display_name() << "' has already been defined"; else cpp_typecheck.str << "symbol `" << symbol.display_name() << "' already has an initializer"; throw 0; #endif } }
void xml_symbol_convertt::convert(const symbolt& sym, xmlt &root) { xmlt &xmlsym = root.new_element("symbol"); irepcache.push_back(irept()); sym.to_irep(irepcache.back()); irepconverter.reference_convert(irepcache.back(), xmlsym); }
void xml_symbol_convertt::convert(const xmlt &xmlsym, symbolt& symbol) { irept t; irepconverter.convert(xmlsym, t); irepconverter.resolve_references(t); symbol.from_irep(t); }
void assign_in_cprover_init(goto_functionst &gf, symbolt &symbol, const exprt &value) { symbol.value=value; goto_programt &body=get_body(gf, CPROVER_INIT); goto_programt::instructionst &instrs=body.instructions; const auto p(std::mem_fun_ref(&goto_programt::instructiont::is_end_function)); goto_programt::targett pos=std::find_if(instrs.begin(), instrs.end(), p); assert(instrs.end() != pos); pos=insert_before_preserving_source_location(body, pos); pos->type=goto_program_instruction_typet::ASSIGN; const symbol_exprt lhs(symbol.symbol_expr()); pos->code=code_assignt(lhs, value); }
void cpp_declarator_convertert::combine_types( const source_locationt &source_location, const typet &decl_type, symbolt &symbol) { if(symbol.type.id()==decl_type.id() && decl_type.id()==ID_code) { // functions need special treatment due // to argument names, default values, and inlined-ness const code_typet &decl_code_type=to_code_type(decl_type); code_typet &symbol_code_type=to_code_type(symbol.type); if(decl_code_type.get_inlined()) symbol_code_type.set_inlined(true); if(decl_code_type.return_type()==symbol_code_type.return_type() && decl_code_type.parameters().size()==symbol_code_type.parameters().size()) { for(unsigned i=0; i<decl_code_type.parameters().size(); i++) { const code_typet::parametert &decl_parameter=decl_code_type.parameters()[i]; code_typet::parametert &symbol_parameter=symbol_code_type.parameters()[i]; // first check type if(decl_parameter.type()!=symbol_parameter.type()) { // The 'this' parameter of virtual functions mismatches if(i!=0 || !symbol_code_type.get_bool("#is_virtual")) { cpp_typecheck.err_location(source_location); cpp_typecheck.str << "symbol `" << symbol.display_name() << "': parameter " << (i+1) << " type mismatch" << std::endl; cpp_typecheck.str << "previous type: " << cpp_typecheck.to_string(symbol_parameter.type()) << std::endl; cpp_typecheck.str << "new type: " << cpp_typecheck.to_string(decl_parameter.type()); throw 0; } } if(symbol.value.is_nil()) { symbol_parameter.set_base_name(decl_parameter.get_base_name()); symbol_parameter.set_identifier(decl_parameter.get_identifier()); symbol_parameter.add_source_location()=decl_parameter.source_location(); } } // ok return; } } else if(symbol.type==decl_type) return; // ok else if(symbol.type.id()==ID_array && symbol.type.find(ID_size).is_nil() && decl_type.id()==ID_array && symbol.type.subtype()==decl_type.subtype()) { symbol.type = decl_type; return; // ok } cpp_typecheck.err_location(source_location); cpp_typecheck.str << "symbol `" << symbol.display_name() << "' already declared with different type:" << std::endl; cpp_typecheck.str << "original: " << cpp_typecheck.to_string(symbol.type) << std::endl; cpp_typecheck.str << " new: " << cpp_typecheck.to_string(final_type); throw 0; }
void c_typecheck_baset::typecheck_symbol(symbolt &symbol) { current_symbol_id=symbol.name; bool is_function=symbol.type.id()==ID_code; const typet &final_type=follow(symbol.type); // set a few flags symbol.is_lvalue=!symbol.is_type && !symbol.is_macro; irep_idt root_name=symbol.base_name; irep_idt new_name=symbol.name; if(symbol.is_file_local) { // file-local stuff -- stays as is // collisions are resolved during linking } else if(symbol.is_extern && !is_function) { // variables marked as "extern" go into the global namespace // and have static lifetime new_name=root_name; symbol.is_static_lifetime=true; } else if(!is_function && symbol.value.id()==ID_code) { err_location(symbol.value); throw "only functions can have a function body"; } // set the pretty name if(symbol.is_type && (final_type.id()==ID_struct || final_type.id()==ID_incomplete_struct)) { symbol.pretty_name="struct "+id2string(symbol.base_name); } else if(symbol.is_type && (final_type.id()==ID_union || final_type.id()==ID_incomplete_union)) { symbol.pretty_name="union "+id2string(symbol.base_name); } else if(symbol.is_type && (final_type.id()==ID_c_enum || final_type.id()==ID_incomplete_c_enum)) { symbol.pretty_name="enum "+id2string(symbol.base_name); } else { symbol.pretty_name=new_name; } // see if we have it already symbol_tablet::symbolst::iterator old_it=symbol_table.symbols.find(symbol.name); if(old_it==symbol_table.symbols.end()) { // just put into symbol_table symbolt *new_symbol; move_symbol(symbol, new_symbol); typecheck_new_symbol(*new_symbol); } else { if(old_it->second.is_type!=symbol.is_type) { err_location(symbol.location); str << "redeclaration of `" << symbol.display_name() << "' as a different kind of symbol"; throw 0; } if(symbol.is_type) typecheck_redefinition_type(old_it->second, symbol); else typecheck_redefinition_non_type(old_it->second, symbol); } }
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. }
void c_typecheck_baset::typecheck_redefinition_type( symbolt &old_symbol, symbolt &new_symbol) { const typet &final_old=follow(old_symbol.type); const typet &final_new=follow(new_symbol.type); // see if we had s.th. incomplete before if(final_old.id()==ID_incomplete_struct || final_old.id()==ID_incomplete_union || final_old.id()==ID_incomplete_c_enum) { // new one complete? if("incomplete_"+final_new.id_string()==final_old.id_string()) { // overwrite location old_symbol.location=new_symbol.location; // move body old_symbol.type.swap(new_symbol.type); } else if(new_symbol.type.id()==old_symbol.type.id()) return; else { err_location(new_symbol.location); str << "error: conflicting definition of type symbol `" << new_symbol.display_name() << "'"; throw 0; } } else { // see if new one is just a tag if(final_new.id()==ID_incomplete_struct || final_new.id()==ID_incomplete_union || final_new.id()==ID_incomplete_c_enum) { if("incomplete_"+final_old.id_string()==final_new.id_string()) { // just ignore silently } else { // arg! new tag type err_location(new_symbol.location); str << "error: conflicting definition of tag symbol `" << new_symbol.display_name() << "'"; throw 0; } } else if(config.ansi_c.os==configt::ansi_ct::ost::OS_WIN && final_new.id()==ID_c_enum && final_old.id()==ID_c_enum) { // under Windows, ignore this silently; // MSC doesn't think this is a problem, but GCC complains. } else if(config.ansi_c.os==configt::ansi_ct::ost::OS_WIN && final_new.id()==ID_pointer && final_old.id()==ID_pointer && follow(final_new.subtype()).id()==ID_c_enum && follow(final_old.subtype()).id()==ID_c_enum) { // under Windows, ignore this silently; // MSC doesn't think this is a problem, but GCC complains. } else { // see if it changed if(follow(new_symbol.type)!=follow(old_symbol.type)) { err_location(new_symbol.location); str << "error: type symbol `" << new_symbol.display_name() << "' defined twice:" << "\n"; str << "Original: " << to_string(old_symbol.type) << "\n"; str << " New: " << to_string(new_symbol.type); throw 0; } } } }
void linkingt::duplicate_non_type_symbol( symbolt &old_symbol, symbolt &new_symbol) { // We first take care of file-local non-type symbols. // These are static functions, or static variables // inside function bodies. if(new_symbol.is_file_local || old_symbol.is_file_local) { // we just always rename these irep_idt old_identifier=new_symbol.name; irep_idt new_identifier=rename(old_identifier); replace_symbol.insert( old_identifier, symbol_exprt(new_identifier, new_symbol.type)); new_symbol.name=new_identifier; // move over! bool result=main_context.move(new_symbol); assert(!result); return; } // see if it is a function or a variable bool is_code_old_symbol=old_symbol.type.id()==ID_code; bool is_code_new_symbol=new_symbol.type.id()==ID_code; if(is_code_old_symbol!=is_code_new_symbol) { err_location(new_symbol.location); str << "error: conflicting definition for symbol \"" << old_symbol.display_name() << "\"" << std::endl; str << "old definition: " << to_string(old_symbol.type) << std::endl; str << "Module: " << old_symbol.module << std::endl; str << "new definition: " << to_string(new_symbol.type) << std::endl; str << "Module: " << new_symbol.module; throw 0; } if(is_code_old_symbol) { // Both are functions. // We don't compare the types, they will be too different; // we just care about the code if(!new_symbol.value.is_nil()) { if(old_symbol.value.is_nil()) { // the one with body wins! old_symbol.value=new_symbol.value; old_symbol.type=new_symbol.type; // for argument identifiers } else if(to_code_type(old_symbol.type).get_inlined()) { // ok } else if(base_type_eq(old_symbol.type, new_symbol.type, ns)) { // keep the one in old_symbol -- libraries come last! str << "warning: function `" << old_symbol.name << "' in module `" << new_symbol.module << "' is shadowed by a definition in module `" << old_symbol.module << "'"; warning(); } else { err_location(new_symbol.value); str << "error: duplicate definition of function `" << old_symbol.name << "'" << std::endl; str << "In module `" << old_symbol.module << "' and module `" << new_symbol.module << "'"; throw 0; } } } else { // both are variables if(!base_type_eq(old_symbol.type, new_symbol.type, ns)) { if(ns.follow(old_symbol.type).id()==ID_array && ns.follow(new_symbol.type).id()==ID_array) { if(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 } else if(ns.follow(old_symbol.type).id()==ID_pointer && ns.follow(new_symbol.type).id()==ID_array) { // store new type old_symbol.type=new_symbol.type; } else if(ns.follow(old_symbol.type).id()==ID_array && ns.follow(new_symbol.type).id()==ID_pointer) { // ignore } else if(ns.follow(old_symbol.type).id()==ID_pointer && ns.follow(new_symbol.type).id()==ID_pointer) { // ignore, generally ok } else if(old_symbol.type.id()==ID_incomplete_struct && new_symbol.type.id()==ID_struct) { // store new type old_symbol.type=new_symbol.type; } else if(old_symbol.type.id()==ID_struct && new_symbol.type.id()==ID_incomplete_struct) { // ignore } else { err_location(new_symbol.location); str << "error: conflicting definition for variable `" << old_symbol.name << "'" << std::endl; str << "old definition: " << to_string_verbose(old_symbol.type) << std::endl; str << "Module: " << old_symbol.module << std::endl; str << "new definition: " << to_string_verbose(new_symbol.type) << std::endl; str << "Module: " << new_symbol.module; throw 0; } } // care about initializers if(!new_symbol.value.is_nil() && !new_symbol.value.get_bool(ID_C_zero_initializer)) { if(old_symbol.value.is_nil() || old_symbol.value.get_bool(ID_C_zero_initializer)) { // new_symbol wins old_symbol.value=new_symbol.value; } else { // try simplifier exprt tmp_old=old_symbol.value, tmp_new=new_symbol.value; simplify(tmp_old, ns); simplify(tmp_new, ns); if(base_type_eq(tmp_old, tmp_new, ns)) { // ok, the same } else { err_location(new_symbol.value); str << "error: conflicting initializers for variable `" << old_symbol.name << "'" << std::endl; str << "old value: " << to_string(tmp_old) << std::endl; str << "Module: " << old_symbol.module << std::endl; str << "new value: " << to_string(tmp_new) << std::endl; str << "Module: " << new_symbol.module; throw 0; } } } } }
void ansi_c_declarationt::to_symbol( const ansi_c_declaratort &declarator, symbolt &symbol) const { symbol.clear(); symbol.value=declarator.value(); symbol.type=full_type(declarator); symbol.name=declarator.get_name(); symbol.base_name=declarator.get_base_name(); symbol.is_type=get_is_typedef(); symbol.location=declarator.source_location(); symbol.is_extern=get_is_extern(); symbol.is_macro=get_is_typedef() || get_is_enum_constant(); symbol.is_parameter=get_is_parameter(); // is it a function? if(symbol.type.id()==ID_code && !symbol.is_type) { symbol.is_static_lifetime=false; symbol.is_thread_local=false; symbol.is_file_local=get_is_static(); if(get_is_inline()) symbol.type.set(ID_C_inlined, true); if(config.ansi_c.mode==configt::ansi_ct::flavourt::MODE_GCC_C || config.ansi_c.mode==configt::ansi_ct::flavourt::MODE_ARM_C_CPP) { // GCC extern inline cleanup, to enable remove_internal_symbols // do its full job // https://gcc.gnu.org/ml/gcc/2006-11/msg00006.html // __attribute__((__gnu_inline__)) if(get_is_inline()) { if(get_is_static()) // C99 and above symbol.is_extern=false; else if(get_is_extern()) // traditional GCC symbol.is_file_local=true; } } } else // non-function { symbol.is_static_lifetime= !symbol.is_macro && !symbol.is_type && (get_is_global() || get_is_static()); symbol.is_thread_local= (!symbol.is_static_lifetime && !get_is_extern()) || get_is_thread_local(); symbol.is_file_local= symbol.is_macro || (!get_is_global() && !get_is_extern()) || (get_is_global() && get_is_static()) || symbol.is_parameter; } }
void symbol_serializationt::convert(const symbolt& sym, std::ostream &out) { irepcache.push_back(irept()); sym.to_irep(irepcache.back()); irepconverter.reference_convert(irepcache.back(), out); }
void java_record_outputs( const symbolt &function, const exprt::operandst &main_arguments, code_blockt &init_code, symbol_tablet &symbol_table) { const code_typet::parameterst ¶meters= 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); } } // record exceptional return variable as output codet output(ID_output); output.operands().resize(2); assert(symbol_table.has_symbol(id2string(function.name)+EXC_SUFFIX)); // retrieve the exception variable const symbolt exc_symbol=symbol_table.lookup( id2string(function.name)+EXC_SUFFIX); output.op0()=address_of_exprt( index_exprt(string_constantt(exc_symbol.base_name), from_integer(0, index_type()))); output.op1()=exc_symbol.symbol_expr(); output.add_source_location()=function.location; init_code.move_to_operands(output); }