void cpp_typecheckt::static_initialization() { code_blockt block_sini; // Static Initialization Block code_blockt block_dini; // Dynamic Initialization Block disable_access_control = true; // first do zero initialization context.foreach_operand([this, &block_sini](const symbolt &s) { if(!s.static_lifetime || s.mode != current_mode) return; // it has a non-code initializer already? if(s.value.is_not_nil() && s.value.id() != "code") return; // it's a declaration only if(s.is_extern) return; if(!s.lvalue) return; zero_initializer( cpp_symbol_expr(s), s.type, s.location, block_sini.operands()); }); while(!dinis.empty()) { symbolt &symbol = *context.find_symbol(dinis.front()); dinis.pop_front(); if(symbol.is_extern) continue; if(symbol.mode != current_mode) continue; assert(symbol.static_lifetime); assert(!symbol.is_type); assert(symbol.type.id() != "code"); exprt symexpr = cpp_symbol_expr(symbol); if(symbol.value.is_not_nil()) { if(!cpp_is_pod(symbol.type)) { block_dini.move_to_operands(symbol.value); } else { exprt symbexpr("symbol", symbol.type); symbexpr.identifier(symbol.name); codet code; code.set_statement("assign"); code.copy_to_operands(symbexpr, symbol.value); code.location() = symbol.location; if(symbol.value.id() == "constant") block_sini.move_to_operands(code); else block_dini.move_to_operands(code); } // Make it nil because we do not want // global_init to try to initialize the // object symbol.value.make_nil(); } else { exprt::operandst ops; codet call = cpp_constructor(locationt(), symexpr, ops); if(call.is_not_nil()) block_dini.move_to_operands(call); } } block_sini.move_to_operands(block_dini); // Create the initialization procedure symbolt init_symbol; init_symbol.name = "#ini#" + id2string(module); init_symbol.base_name = "#ini#" + id2string(module); init_symbol.value.swap(block_sini); init_symbol.mode = current_mode; init_symbol.module = module; init_symbol.type = code_typet(); init_symbol.type.add("return_type") = typet("empty"); init_symbol.type.set("initialization", true); init_symbol.is_type = false; init_symbol.is_macro = false; context.move(init_symbol); disable_access_control = false; }
void cpp_typecheckt::convert_non_template_declaration( cpp_declarationt &declaration) { assert(!declaration.is_template()); // we first check if this is a typedef typet &declaration_type=declaration.type(); bool is_typedef=declaration.is_typedef(); declaration.name_anon_struct_union(); typecheck_type(declaration_type); // Elaborate any class template instance _unless_ we do a typedef. // These are only elaborated on usage! if(!is_typedef) elaborate_class_template(declaration_type); // Special treatment for anonymous unions if(declaration.declarators().empty() && follow(declaration.type()).get_bool(ID_C_is_anonymous)) { typet final_type=follow(declaration.type()); if(final_type.id()!=ID_union) { error().source_location=final_type.source_location(); error() << "top-level declaration does not declare anything" << eom; throw 0; } codet dummy; convert_anonymous_union(declaration, dummy); } // do the declarators (optional) Forall_cpp_declarators(it, declaration) { // copy the declarator (we destroy the original) cpp_declaratort declarator=*it; cpp_declarator_convertert cpp_declarator_converter(*this); cpp_declarator_converter.is_typedef=is_typedef; symbolt &symbol=cpp_declarator_converter.convert( declaration_type, declaration.storage_spec(), declaration.member_spec(), declarator); // any template instance to remember? if(declaration.find(ID_C_template).is_not_nil()) { symbol.type.set(ID_C_template, declaration.find(ID_C_template)); symbol.type.set(ID_C_template_arguments, declaration.find(ID_C_template_arguments)); } // replace declarator by symbol expression exprt tmp=cpp_symbol_expr(symbol); it->swap(tmp); // is there a constructor to be called for the declarator? if(symbol.is_lvalue && declarator.init_args().has_operands()) { symbol.value= cpp_constructor( symbol.location, cpp_symbol_expr(symbol), declarator.init_args().operands()); } }
void cpp_typecheckt::convert_anonymous_union( cpp_declarationt &declaration, codet &code) { codet new_code(ID_decl_block); new_code.reserve_operands(declaration.declarators().size()); // unnamed object std::string identifier="#anon_union"+i2string(anon_counter++); irept name(ID_name); name.set(ID_identifier, identifier); name.set(ID_C_source_location, declaration.source_location()); cpp_namet cpp_name; cpp_name.move_to_sub(name); cpp_declaratort declarator; declarator.name()=cpp_name; cpp_declarator_convertert cpp_declarator_converter(*this); const symbolt &symbol= cpp_declarator_converter.convert(declaration, declarator); if(!cpp_is_pod(declaration.type())) { error().source_location=follow(declaration.type()).source_location(); error() << "anonymous union is not POD" << eom; throw 0; } codet decl_statement(ID_decl); decl_statement.reserve_operands(2); decl_statement.copy_to_operands(cpp_symbol_expr(symbol)); new_code.move_to_operands(decl_statement); // do scoping symbolt union_symbol=symbol_table.symbols[follow(symbol.type).get(ID_name)]; const irept::subt &components=union_symbol.type.add(ID_components).get_sub(); forall_irep(it, components) { if(it->find(ID_type).id()==ID_code) { error().source_location=union_symbol.type.source_location(); error() << "anonymous union `" << union_symbol.base_name << "' shall not have function members" << eom; throw 0; } const irep_idt &base_name=it->get(ID_base_name); if(cpp_scopes.current_scope().contains(base_name)) { error().source_location=union_symbol.type.source_location(); error() << "identifier `" << base_name << "' already in scope" << eom; throw 0; } cpp_idt &id=cpp_scopes.current_scope().insert(base_name); id.id_class = cpp_idt::SYMBOL; id.identifier=it->get(ID_name); id.class_identifier=union_symbol.name; id.is_member=true; } symbol_table.symbols[union_symbol.name].type.set( "#unnamed_object", symbol.base_name); code.swap(new_code); }
void cpp_typecheckt::typecheck_friend_declaration( symbolt &symbol, cpp_declarationt &declaration) { // A friend of a class can be a function/method, // or a struct/class/union type. if(declaration.is_template()) { return; // TODO err_location(declaration.type().location()); str << "friend template not supported"; throw 0; } // we distinguish these whether there is a declarator if(declaration.declarators().empty()) { typet &ftype=declaration.type(); // must be struct or union if(ftype.id()!=ID_struct && ftype.id()!=ID_union) { err_location(declaration.type()); str << "unexpected friend"; throw 0; } if(ftype.find(ID_body).is_not_nil()) { err_location(declaration.type()); str << "friend declaration must not have compound body"; throw 0; } // typecheck ftype // TODO // typecheck_type(ftype); // assert(ftype.id()==ID_symbol); // symbol.type.add("#friends").move_to_sub(ftype); return; } // It should be a friend function. // Do the declarators. Forall_cpp_declarators(sub_it, declaration) { bool has_value = sub_it->value().is_not_nil(); if(!has_value) { // If no value is found, then we jump to the // global scope, and we convert the declarator // as if it were declared there cpp_save_scopet saved_scope(cpp_scopes); cpp_scopes.go_to_global_scope(); cpp_declarator_convertert cpp_declarator_converter(*this); const symbolt &conv_symb = cpp_declarator_converter.convert( declaration.type(), declaration.storage_spec(), declaration.member_spec(), *sub_it); exprt symb_expr = cpp_symbol_expr(conv_symb); symbol.type.add("#friends").move_to_sub(symb_expr); } else { cpp_declarator_convertert cpp_declarator_converter(*this); cpp_declarator_converter.is_friend = true; declaration.member_spec().set_inline(true); const symbolt &conv_symb = cpp_declarator_converter.convert( declaration.type(), declaration.storage_spec(), declaration.member_spec(), *sub_it); exprt symb_expr = cpp_symbol_expr(conv_symb); symbol.type.add("#friends").move_to_sub(symb_expr); } }