symbolt &cpp_declarator_convertert::convert_new_symbol( const cpp_storage_spect &storage_spec, const cpp_member_spect &member_spec, cpp_declaratort &declarator) { irep_idt pretty_name=get_pretty_name(); symbolt symbol; symbol.name=final_identifier; symbol.base_name=base_name; symbol.value=declarator.value(); symbol.location=declarator.name().source_location(); symbol.mode=linkage_spec==ID_auto?ID_cpp:linkage_spec; symbol.module=cpp_typecheck.module; symbol.type=final_type; symbol.is_type=is_typedef; symbol.is_macro=is_typedef && !is_template_parameter; symbol.pretty_name=pretty_name; // Constant? These are propagated. if(symbol.type.get_bool(ID_C_constant) && symbol.value.is_not_nil()) symbol.is_macro=true; if(member_spec.is_inline()) symbol.type.set(ID_C_inlined, true); if(!symbol.is_type) { if(is_code) { // it is a function if(storage_spec.is_static()) symbol.is_file_local=true; } else { // it is a variable symbol.is_state_var=true; symbol.is_lvalue = !is_reference(symbol.type) && !(symbol.type.get_bool(ID_C_constant) && is_number(symbol.type) && symbol.value.id() == ID_constant); if(cpp_typecheck.cpp_scopes.current_scope().is_global_scope()) { symbol.is_static_lifetime=true; if(storage_spec.is_extern()) symbol.is_extern=true; } else { if(storage_spec.is_static()) { symbol.is_static_lifetime=true; symbol.is_file_local=true; } else if(storage_spec.is_extern()) { cpp_typecheck.err_location(storage_spec); throw "external storage not permitted here"; } } } } if(symbol.is_static_lifetime) cpp_typecheck.dynamic_initializations.push_back(symbol.name); // move early, it must be visible before doing any value symbolt *new_symbol; if(cpp_typecheck.symbol_table.move(symbol, new_symbol)) throw "cpp_typecheckt::convert_declarator: symbol_table.move() failed"; if(!is_code) { cpp_scopest::id_sett id_set; cpp_typecheck.cpp_scopes.current_scope().lookup( base_name, cpp_scopet::SCOPE_ONLY, id_set); for(cpp_scopest::id_sett::const_iterator id_it=id_set.begin(); id_it!=id_set.end(); id_it++) { const cpp_idt &id=**id_it; // the name is already in the scope // this is ok if they belong to different categories if(!id.is_class() && !id.is_enum()) { cpp_typecheck.err_location(new_symbol->location); cpp_typecheck.str << "`" << base_name << "' already in scope"; throw 0; } } } // put into scope cpp_idt &identifier= cpp_typecheck.cpp_scopes.put_into_scope(*new_symbol, *scope, is_friend); if(is_template) identifier.id_class=cpp_idt::TEMPLATE; else if(is_template_parameter) identifier.id_class=cpp_idt::TEMPLATE_PARAMETER; else if(is_typedef) identifier.id_class=cpp_idt::TYPEDEF; else identifier.id_class=cpp_idt::SYMBOL; // do the value if(!new_symbol->is_type) { if(is_code && declarator.type().id()!=ID_template) cpp_typecheck.add_function_body(new_symbol); if(!is_code) cpp_typecheck.convert_initializer(*new_symbol); } enforce_rules(*new_symbol); return *new_symbol; }
symbolt &cpp_declarator_convertert::convert_new_symbol( const cpp_storage_spect &storage_spec, const cpp_member_spect &member_spec, cpp_declaratort &declarator) { irep_idt pretty_name=get_pretty_name(); symbolt symbol; symbol.name=final_identifier; symbol.base_name=base_name; symbol.value=declarator.value(); symbol.location=declarator.name().location(); symbol.mode=mode; symbol.module=cpp_typecheck.module; symbol.type=final_type; symbol.is_type=is_typedef; symbol.is_macro=is_typedef && !is_template_argument; symbol.pretty_name=pretty_name; symbol.mode=cpp_typecheck.current_mode; // We always insert throw_decl to the begin of the function if(declarator.throw_decl().statement()=="throw_decl") { symbol.value.operands().insert( symbol.value.operands().begin(), declarator.throw_decl()); // Insert flag to end of constructor // so we know when to remove throw_decl symbol.value.operands().push_back( codet("throw_decl_end")); } // Constant? These are propagated. if(symbol.type.cmt_constant() && symbol.value.is_not_nil()) symbol.is_macro=true; if(member_spec.is_inline()) symbol.type.set("#inlined", true); if(!symbol.is_type) { if(!is_code) { // it is a variable symbol.is_statevar=true; symbol.lvalue = !is_reference(symbol.type) && !(symbol.type.cmt_constant() && is_number(symbol.type) && symbol.value.id() == "constant"); if(cpp_typecheck.cpp_scopes.current_scope().is_global_scope()) { symbol.static_lifetime=true; if(storage_spec.is_extern()) symbol.is_extern=true; } else { if(storage_spec.is_static()) { //symbol.static_lifetime=true; symbol.file_local=true; } else if(storage_spec.is_extern()) { cpp_typecheck.err_location(storage_spec); throw "external storage not permitted here"; } } } } if(symbol.static_lifetime) cpp_typecheck.dinis.push_back(symbol.name); // move early, it must be visible before doing any value symbolt *new_symbol; if(cpp_typecheck.context.move(symbol, new_symbol)) throw "cpp_typecheckt::convert_declarator: context.move() failed"; if(!is_code) { cpp_scopest::id_sett id_set; cpp_typecheck.cpp_scopes.current_scope().lookup( base_name, cpp_scopet::SYMBOL, id_set); for(cpp_scopest::id_sett::const_iterator id_it=id_set.begin(); id_it!=id_set.end(); id_it++) { const cpp_idt &id=**id_it; // the name is already in the scope // this is ok if they belong to different categories if(!id.is_class() && !id.is_enum()) { cpp_typecheck.err_location(new_symbol->location); cpp_typecheck.str << "`" << base_name << "' already in scope"; throw 0; } } } // put into scope cpp_idt &identifier= cpp_typecheck.cpp_scopes.put_into_scope(*new_symbol, *scope, is_friend); if(is_template) identifier.id_class=cpp_idt::TEMPLATE; else if(is_template_argument) identifier.id_class=cpp_idt::TEMPLATE_ARGUMENT; else if(is_typedef) identifier.id_class=cpp_idt::TYPEDEF; else identifier.id_class=cpp_idt::SYMBOL; // do the value if(!new_symbol->is_type) { if(is_code && declarator.type().id()!="template") cpp_typecheck.add_function_body(new_symbol); if(!is_code && !declarator.find("name").get_bool("catch_decl")) cpp_typecheck.convert_initializer(*new_symbol); } enforce_rules(*new_symbol); return *new_symbol; }