void java_bytecode_convertt::add_array_types() { const char letters[]="ijsbcfdza"; for(unsigned i=0; letters[i]!=0; i++) { symbol_typet symbol_type= to_symbol_type(java_array_type(letters[i]).subtype()); struct_typet struct_type; // we have the base class, java.lang.Object, length and data // of appropriate type struct_type.set_tag(symbol_type.get_identifier()); struct_type.components().resize(3); struct_type.components()[0].set_name("@java.lang.Object"); struct_type.components()[0].type()=symbol_typet("java::java.lang.Object"); struct_type.components()[1].set_name("length"); struct_type.components()[1].type()=java_int_type(); struct_type.components()[2].set_name("data"); struct_type.components()[2].type()= pointer_typet(java_type_from_char(letters[i])); symbolt symbol; symbol.name=symbol_type.get_identifier(); symbol.base_name=symbol_type.get(ID_C_base_name); symbol.is_type=true; symbol.type=struct_type; symbol_table.add(symbol); } }
void linkingt::rename_type_symbol(symbolt &new_symbol) { replace_symbolt::type_mapt::const_iterator replace_entry= replace_symbol.type_map.find(new_symbol.name); if(replace_entry!=replace_symbol.type_map.end()) { new_symbol.name=to_symbol_type(replace_entry->second).get_identifier(); } else { // rename! irep_idt old_identifier=new_symbol.name; irep_idt new_identifier=rename(old_identifier); replace_symbol.insert(old_identifier, symbol_typet(new_identifier)); new_symbol.name=new_identifier; } // need to replace again replace_symbol.replace(new_symbol.type); // move over! bool result=main_context.move(new_symbol); assert(!result); }
void java_bytecode_convert_classt::add_array_types() { const std::string letters="ijsbcfdza"; for(const char l : letters) { symbol_typet symbol_type= to_symbol_type(java_array_type(l).subtype()); struct_typet struct_type; // we have the base class, java.lang.Object, length and data // of appropriate type struct_type.set_tag(symbol_type.get_identifier()); struct_type.components().reserve(3); struct_typet::componentt comp0("@java.lang.Object", symbol_typet("java::java.lang.Object")); struct_type.components().push_back(comp0); struct_typet::componentt comp1("length", java_int_type()); struct_type.components().push_back(comp1); struct_typet::componentt comp2("data", pointer_typet(java_type_from_char(l))); struct_type.components().push_back(comp2); symbolt symbol; symbol.name=symbol_type.get_identifier(); symbol.base_name=symbol_type.get(ID_C_base_name); symbol.is_type=true; symbol.type=struct_type; symbol_table.add(symbol); } }
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); } }
void remove_virtual_functionst::remove_virtual_function( goto_programt &goto_program, goto_programt::targett target) { const code_function_callt &code= to_code_function_call(target->code); const auto &vcall_source_loc=target->source_location; const exprt &function=code.function(); assert(function.id()==ID_virtual_function); assert(!code.arguments().empty()); functionst functions; get_functions(function, functions); if(functions.empty()) { target->make_skip(); return; // give up } // only one option? if(functions.size()==1) { assert(target->is_function_call()); if(functions.begin()->symbol_expr==symbol_exprt()) target->make_skip(); else to_code_function_call(target->code).function()= functions.begin()->symbol_expr; return; } // the final target is a skip goto_programt final_skip; goto_programt::targett t_final=final_skip.add_instruction(); t_final->source_location=vcall_source_loc; t_final->make_skip(); // build the calls and gotos goto_programt new_code_calls; goto_programt new_code_gotos; exprt this_expr=code.arguments()[0]; // If necessary, cast to the last candidate function to // get the object's clsid. By the structure of get_functions, // this is the parent of all other classes under consideration. const auto &base_classid=functions.back().class_id; const auto &base_function_symbol=functions.back().symbol_expr; symbol_typet suggested_type(base_classid); exprt c_id2=get_class_identifier_field(this_expr, suggested_type, ns); std::map<irep_idt, goto_programt::targett> calls; // Note backwards iteration, to get the least-derived candidate first. for(auto it=functions.crbegin(), itend=functions.crend(); it!=itend; ++it) { const auto &fun=*it; auto insertit=calls.insert( {fun.symbol_expr.get_identifier(), goto_programt::targett()}); // Only create one call sequence per possible target: if(insertit.second) { goto_programt::targett t1=new_code_calls.add_instruction(); t1->source_location=vcall_source_loc; if(!fun.symbol_expr.get_identifier().empty()) { // call function t1->make_function_call(code); auto &newcall=to_code_function_call(t1->code); newcall.function()=fun.symbol_expr; pointer_typet need_type(symbol_typet(fun.symbol_expr.get(ID_C_class))); if(!type_eq(newcall.arguments()[0].type(), need_type, ns)) newcall.arguments()[0].make_typecast(need_type); } else { // No definition for this type; shouldn't be possible... t1->make_assertion(false_exprt()); } insertit.first->second=t1; // goto final goto_programt::targett t3=new_code_calls.add_instruction(); t3->source_location=vcall_source_loc; t3->make_goto(t_final, true_exprt()); } // If this calls the base function we just fall through. // Otherwise branch to the right call: if(fun.symbol_expr!=base_function_symbol) { exprt c_id1=constant_exprt(fun.class_id, string_typet()); goto_programt::targett t4=new_code_gotos.add_instruction(); t4->source_location=vcall_source_loc; t4->make_goto(insertit.first->second, equal_exprt(c_id1, c_id2)); } } goto_programt new_code; // patch them all together new_code.destructive_append(new_code_gotos); new_code.destructive_append(new_code_calls); new_code.destructive_append(final_skip); // set locations Forall_goto_program_instructions(it, new_code) { const irep_idt property_class=it->source_location.get_property_class(); const irep_idt comment=it->source_location.get_comment(); it->source_location=target->source_location; it->function=target->function; if(!property_class.empty()) it->source_location.set_property_class(property_class); if(!comment.empty()) it->source_location.set_comment(comment); } goto_programt::targett next_target=target; next_target++; goto_program.destructive_insert(next_target, new_code); // finally, kill original invocation target->make_skip(); }
symbol_typet jsa_heap_type() { return symbol_typet(JSA_HEAP_TAG); }
symbol_typet jsa_query_instruction_type() { return symbol_typet(QUERY_INSTR_TYPE); }
symbol_typet jsa_invariant_instruction_type() { return symbol_typet(INV_INSTR_TYPE); }
symbol_typet jsa_predicate_instruction_type() { return symbol_typet(PRED_INSTR_TYPE); }
void cpp_typecheckt::do_virtual_table(const symbolt &symbol) { assert(symbol.type.id()==ID_struct); // builds virtual-table value maps: (class x virtual_name x value) std::map<irep_idt, std::map<irep_idt,exprt> > vt_value_maps; const struct_typet &struct_type = to_struct_type(symbol.type); for(unsigned i = 0; i < struct_type.components().size(); i++) { const struct_typet::componentt& compo = struct_type.components()[i]; if(!compo.get_bool("is_virtual")) continue; const code_typet& code_type = to_code_type(compo.type()); assert(code_type.arguments().size() > 0); const pointer_typet& pointer_type = static_cast<const pointer_typet&>(code_type.arguments()[0].type()); irep_idt class_id = pointer_type.subtype().get("identifier"); std::map<irep_idt,exprt>& value_map = vt_value_maps[class_id]; exprt e = symbol_exprt(compo.get_name(),code_type); if(compo.get_bool("is_pure_virtual")) { pointer_typet pointer_type(code_type); e = gen_zero(pointer_type); assert(e.is_not_nil()); value_map[compo.get("virtual_name")] = e; } else { address_of_exprt address(e); value_map[compo.get("virtual_name")] = address; } } // create virtual-table symbol variables for(std::map<irep_idt, std::map<irep_idt,exprt> >::const_iterator cit = vt_value_maps.begin(); cit != vt_value_maps.end(); cit++) { const std::map<irep_idt,exprt>& value_map = cit->second; const symbolt& late_cast_symb = namespacet(symbol_table).lookup(cit->first); const symbolt& vt_symb_type = namespacet(symbol_table).lookup("virtual_table::"+id2string(late_cast_symb.name)); symbolt vt_symb_var; vt_symb_var.name= id2string(vt_symb_type.name) + "@"+ id2string(symbol.name); vt_symb_var.base_name= id2string(vt_symb_type.base_name) + "@" + id2string(symbol.base_name); vt_symb_var.mode=ID_cpp; vt_symb_var.module=module; vt_symb_var.location=vt_symb_type.location; vt_symb_var.type = symbol_typet(vt_symb_type.name); vt_symb_var.is_lvalue = true; vt_symb_var.is_static_lifetime = true; // do the values const struct_typet &vt_type = to_struct_type(vt_symb_type.type); exprt values(ID_struct, symbol_typet(vt_symb_type.name)); for(unsigned i=0; i < vt_type.components().size(); i++) { const struct_typet::componentt& compo = vt_type.components()[i]; std::map<irep_idt,exprt>::const_iterator cit2 = value_map.find( compo.get("base_name")); assert(cit2 != value_map.end()); const exprt& value = cit2->second; assert(value.type() == compo.type()); values.operands().push_back(value); } vt_symb_var.value = values; bool failed = symbol_table.move(vt_symb_var); assert(!failed); } }
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); }
typet java_type_from_string(const std::string &src) { if(src.empty()) return nil_typet(); switch(src[0]) { case '(': // function type { std::size_t e_pos=src.rfind(')'); if(e_pos==std::string::npos) return nil_typet(); code_typet result; result.return_type()= java_type_from_string(std::string(src, e_pos+1, std::string::npos)); for(std::size_t i=1; i<src.size() && src[i]!=')'; i++) { code_typet::parametert param; size_t start=i; while(i<src.size()) { if(src[i]=='L') { i=src.find(';', i); // ends on ; break; } else if(src[i]=='[') i++; else break; } std::string sub_str=src.substr(start, i-start+1); param.type()=java_type_from_string(sub_str); if(param.type().id()==ID_symbol) param.type()=java_reference_type(param.type()); result.parameters().push_back(param); } return result; } case '[': // array type { if(src.size()<=2) return nil_typet(); typet subtype=java_type_from_string(src.substr(1, std::string::npos)); return java_reference_type(java_array_type(subtype)); } case 'F': return java_float_type(); case 'D': return java_double_type(); case 'I': return java_int_type(); case 'C': return java_char_type(); case 'Z': return java_boolean_type(); case 'V': return java_void_type(); case 'J': return java_long_type(); case 'L': { // ends on ; if(src[src.size()-1]!=';') return nil_typet(); std::string identifier="java::"+src.substr(1, src.size()-2); for(unsigned i=0; i<identifier.size(); i++) if(identifier[i]=='/') identifier[i]='.'; reference_typet result; result.subtype()=symbol_typet(identifier); return result; } default: return nil_typet(); } }
void cpp_typecheckt::typecheck_compound_declarator( const symbolt &symbol, const cpp_declarationt &declaration, cpp_declaratort &declarator, struct_typet::componentst &components, const irep_idt &access, bool is_static, bool is_typedef, bool is_mutable) { bool is_cast_operator= declaration.type().id()=="cpp-cast-operator"; if(is_cast_operator) { assert(declarator.name().get_sub().size()==2 && declarator.name().get_sub().front().id()==ID_operator); typet type=static_cast<typet &>(declarator.name().get_sub()[1]); declarator.type().subtype()=type; irept name(ID_name); name.set(ID_identifier, "("+cpp_type2name(type)+")"); declarator.name().get_sub().back().swap(name); } typet final_type= declarator.merge_type(declaration.type()); // this triggers template elaboration elaborate_class_template(final_type); typecheck_type(final_type); cpp_namet cpp_name; cpp_name.swap(declarator.name()); irep_idt base_name; if(cpp_name.is_nil()) { // Yes, there can be members without name. base_name=irep_idt(); } else if(cpp_name.is_simple_name()) { base_name=cpp_name.get_base_name(); } else { err_location(cpp_name.location()); str << "declarator in compound needs to be simple name"; throw 0; } bool is_method=!is_typedef && final_type.id()==ID_code; bool is_constructor=declaration.is_constructor(); bool is_destructor=declaration.is_destructor(); bool is_virtual=declaration.member_spec().is_virtual(); bool is_explicit=declaration.member_spec().is_explicit(); bool is_inline=declaration.member_spec().is_inline(); final_type.set(ID_C_member_name, symbol.name); // first do some sanity checks if(is_virtual && !is_method) { err_location(cpp_name.location()); str << "only methods can be virtual"; throw 0; } if(is_inline && !is_method) { err_location(cpp_name.location()); str << "only methods can be inlined"; throw 0; } if(is_virtual && is_static) { err_location(cpp_name.location()); str << "static methods cannot be virtual"; throw 0; } if(is_cast_operator && is_static) { err_location(cpp_name.location()); str << "cast operators cannot be static`"; throw 0; } if(is_constructor && is_virtual) { err_location(cpp_name.location()); str << "constructors cannot be virtual"; throw 0; } if(!is_constructor && is_explicit) { err_location(cpp_name.location()); str << "only constructors can be explicit"; throw 0; } if(is_constructor && base_name!=id2string(symbol.base_name)) { err_location(cpp_name.location()); str << "member function must return a value or void"; throw 0; } if(is_destructor && base_name!="~"+id2string(symbol.base_name)) { err_location(cpp_name.location()); str << "destructor with wrong name"; throw 0; } // now do actual work struct_typet::componentt component; irep_idt identifier= language_prefix+ cpp_scopes.current_scope().prefix+ id2string(base_name); component.set(ID_name, identifier); component.type()=final_type; component.set(ID_access, access); component.set(ID_base_name, base_name); component.set(ID_pretty_name, base_name); component.location()=cpp_name.location(); if(cpp_name.is_operator()) { component.set("is_operator", true); component.type().set("#is_operator", true); } if(is_cast_operator) component.set("is_cast_operator", true); if(declaration.member_spec().is_explicit()) component.set("is_explicit", true); typet &method_qualifier= (typet &)declarator.add("method_qualifier"); if(is_static) { component.set(ID_is_static, true); component.type().set("#is_static", true); } if(is_typedef) component.set("is_type", true); if(is_mutable) component.set("is_mutable", true); exprt &value=declarator.value(); irept &initializers=declarator.member_initializers(); if(is_method) { component.set(ID_is_inline, declaration.member_spec().is_inline()); // the 'virtual' name of the function std::string virtual_name= component.get_string(ID_base_name)+ id2string( function_identifier(static_cast<const typet &>(component.find(ID_type)))); if(method_qualifier.id()==ID_const) virtual_name += "$const"; if(component.type().get(ID_return_type) == ID_destructor) virtual_name= "@dtor"; // The method may be virtual implicitly. std::set<irep_idt> virtual_bases; for(struct_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) { if(it->get_bool("is_virtual")) { if(it->get("virtual_name")==virtual_name) { is_virtual=true; const code_typet& code_type = to_code_type(it->type()); assert(code_type.arguments().size()>0); const typet& pointer_type = code_type.arguments()[0].type(); assert(pointer_type.id() == ID_pointer); virtual_bases.insert(pointer_type.subtype().get(ID_identifier)); } } } if(!is_virtual) { typecheck_member_function( symbol.name, component, initializers, method_qualifier, value); if(!value.is_nil() && !is_static) { err_location(cpp_name.location()); str << "no initialization allowed here"; throw 0; } } else // virtual { component.type().set("#is_virtual", true); component.type().set("#virtual_name",virtual_name); // Check if it is a pure virtual method if(is_virtual) { if(value.is_not_nil() && value.id() == ID_constant) { mp_integer i; to_integer(value, i); if(i!=0) { err_location(declarator.name().location()); str << "expected 0 to mark pure virtual method, got " << i; } component.set("is_pure_virtual", true); value.make_nil(); } } typecheck_member_function( symbol.name, component, initializers, method_qualifier, value); // get the virtual-table symbol type irep_idt vt_name = "virtual_table::"+symbol.name.as_string(); contextt::symbolst::iterator vtit = context.symbols.find(vt_name); if(vtit == context.symbols.end()) { // first time: create a virtual-table symbol type symbolt vt_symb_type; vt_symb_type.name= vt_name; vt_symb_type.base_name="virtual_table::"+symbol.base_name.as_string(); vt_symb_type.pretty_name = vt_symb_type.base_name; vt_symb_type.mode=ID_cpp; vt_symb_type.module=module; vt_symb_type.location=symbol.location; vt_symb_type.type = struct_typet(); vt_symb_type.type.set(ID_name, vt_symb_type.name); vt_symb_type.is_type = true; bool failed = context.move(vt_symb_type); assert(!failed); vtit = context.symbols.find(vt_name); // add a virtual-table pointer struct_typet::componentt compo; compo.type() = pointer_typet(symbol_typet(vt_name)); compo.set_name(symbol.name.as_string() +"::@vtable_pointer"); compo.set(ID_base_name, "@vtable_pointer"); compo.set(ID_pretty_name, symbol.base_name.as_string() +"@vtable_pointer"); compo.set("is_vtptr", true); compo.set(ID_access, ID_public); components.push_back(compo); put_compound_into_scope(compo); } assert(vtit->second.type.id()==ID_struct); struct_typet &virtual_table= to_struct_type(vtit->second.type); component.set("virtual_name", virtual_name); component.set("is_virtual", is_virtual); // add an entry to the virtual table struct_typet::componentt vt_entry; vt_entry.type() = pointer_typet(component.type()); vt_entry.set_name(vtit->first.as_string()+"::"+virtual_name); vt_entry.set(ID_base_name, virtual_name); vt_entry.set(ID_pretty_name, virtual_name); vt_entry.set(ID_access, ID_public); vt_entry.location() = symbol.location; virtual_table.components().push_back(vt_entry); // take care of overloading while(!virtual_bases.empty()) { irep_idt virtual_base = *virtual_bases.begin(); // a new function that does 'late casting' of the 'this' parameter symbolt func_symb; func_symb.name=component.get_name().as_string() + "::" +virtual_base.as_string(); func_symb.base_name=component.get(ID_base_name); func_symb.pretty_name = component.get(ID_base_name); func_symb.mode=ID_cpp; func_symb.module=module; func_symb.location=component.location(); func_symb.type=component.type(); // change the type of the 'this' pointer code_typet& code_type = to_code_type(func_symb.type); code_typet::argumentt& arg= code_type.arguments().front(); arg.type().subtype().set(ID_identifier, virtual_base); // create symbols for the arguments code_typet::argumentst& args = code_type.arguments(); for(unsigned i=0; i<args.size(); i++) { code_typet::argumentt& arg = args[i]; irep_idt base_name = arg.get_base_name(); if(base_name==irep_idt()) base_name="arg"+i2string(i); symbolt arg_symb; arg_symb.name = func_symb.name.as_string() + "::"+ base_name.as_string(); arg_symb.base_name = base_name; arg_symb.pretty_name = base_name; arg_symb.mode=ID_cpp; arg_symb.location=func_symb.location; arg_symb.type = arg.type(); arg.set(ID_C_identifier, arg_symb.name); // add the argument to the symbol table bool failed = context.move(arg_symb); assert(!failed); } // do the body of the function typecast_exprt late_cast(to_code_type(component.type()).arguments()[0].type()); late_cast.op0()= symbol_expr(namespacet(context).lookup( args[0].get(ID_C_identifier))); if(code_type.return_type().id()!=ID_empty && code_type.return_type().id()!=ID_destructor) { side_effect_expr_function_callt expr_call; expr_call.function() = symbol_exprt(component.get_name(),component.type()); expr_call.type() = to_code_type(component.type()).return_type(); expr_call.arguments().reserve(args.size()); expr_call.arguments().push_back(late_cast); for(unsigned i=1; i < args.size(); i++) { expr_call.arguments().push_back( symbol_expr(namespacet(context).lookup( args[i].get(ID_C_identifier)))); } code_returnt code_return; code_return.return_value() = expr_call; func_symb.value = code_return; } else { code_function_callt code_func; code_func.function() = symbol_exprt(component.get_name(),component.type()); code_func.arguments().reserve(args.size()); code_func.arguments().push_back(late_cast); for(unsigned i=1; i < args.size(); i++) { code_func.arguments().push_back( symbol_expr(namespacet(context).lookup( args[i].get(ID_C_identifier)))); } func_symb.value = code_func; } // add this new function to the list of components struct_typet::componentt new_compo = component; new_compo.type() = func_symb.type; new_compo.set_name(func_symb.name); components.push_back(new_compo); // add the function to the symbol table { bool failed = context.move(func_symb); assert(!failed); } // next base virtual_bases.erase(virtual_bases.begin()); } } } if(is_static && !is_method) // static non-method member { // add as global variable to context symbolt static_symbol; static_symbol.mode=symbol.mode; static_symbol.name=identifier; static_symbol.type=component.type(); static_symbol.base_name=component.get(ID_base_name); static_symbol.lvalue=true; static_symbol.static_lifetime=true; static_symbol.location=cpp_name.location(); static_symbol.is_extern=true; // TODO: not sure about this: should be defined separately! dynamic_initializations.push_back(static_symbol.name); symbolt *new_symbol; if(context.move(static_symbol, new_symbol)) { err_location(cpp_name.location()); str << "redeclaration of static member `" << static_symbol.base_name.as_string() << "'"; throw 0; } if(value.is_not_nil()) { if(cpp_is_pod(new_symbol->type)) { new_symbol->value.swap(value); c_typecheck_baset::do_initializer(*new_symbol); // these are macros if they are PODs and come with a (constant) value if(new_symbol->type.get_bool(ID_C_constant)) { simplify(new_symbol->value, *this); new_symbol->is_macro=true; } } else { symbol_exprt symexpr; symexpr.set_identifier(new_symbol->name); exprt::operandst ops; ops.push_back(value); codet defcode = cpp_constructor(locationt(), symexpr, ops); new_symbol->value.swap(defcode); } } } // array members must have fixed size check_fixed_size_array(component.type()); put_compound_into_scope(component); components.push_back(component); }