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); }
cpp_scopet &cpp_typecheckt::typecheck_template_parameters( template_typet &type) { cpp_save_scopet cpp_saved_scope(cpp_scopes); assert(type.id()==ID_template); std::string id_suffix="template::"+i2string(template_counter++); // produce a new scope for the template parameters cpp_scopet &template_scope= cpp_scopes.current_scope().new_scope( cpp_scopes.current_scope().prefix+id_suffix); template_scope.prefix=template_scope.get_parent().prefix+id_suffix; template_scope.id_class=cpp_idt::TEMPLATE_SCOPE; cpp_scopes.go_to(template_scope); // put template parameters into this scope template_typet::template_parameterst ¶meters= type.template_parameters(); unsigned anon_count=0; for(template_typet::template_parameterst::iterator it=parameters.begin(); it!=parameters.end(); it++) { exprt ¶meter=*it; cpp_declarationt declaration; declaration.swap(static_cast<cpp_declarationt &>(parameter)); cpp_declarator_convertert cpp_declarator_converter(*this); // there must be _one_ declarator assert(declaration.declarators().size()==1); cpp_declaratort &declarator=declaration.declarators().front(); // it may be anonymous if(declarator.name().is_nil()) { irept name(ID_name); name.set(ID_identifier, "anon#"+i2string(++anon_count)); declarator.name()=cpp_namet(); declarator.name().get_sub().push_back(name); } #if 1 // The declarator needs to be just a name if(declarator.name().get_sub().size()!=1 || declarator.name().get_sub().front().id()!=ID_name) { err_location(declaration); throw "template parameter must be simple name"; } cpp_scopet &scope=cpp_scopes.current_scope(); irep_idt base_name=declarator.name().get_sub().front().get(ID_identifier); irep_idt identifier=scope.prefix+id2string(base_name); // add to scope cpp_idt &id=scope.insert(base_name); id.identifier=identifier; id.id_class=cpp_idt::TEMPLATE_PARAMETER; // is it a type or not? if(declaration.get_bool(ID_is_type)) { parameter=exprt(ID_type, typet(ID_symbol)); parameter.type().set(ID_identifier, identifier); parameter.type().add_source_location()=declaration.find_source_location(); } else { // The type is not checked, as it might depend // on earlier parameters. typet type=declaration.type(); parameter=symbol_exprt(identifier, type); } // There might be a default type or default value. // We store it for later, as it can't be typechecked now // because of possible dependencies on earlier parameters! if(declarator.value().is_not_nil()) parameter.add(ID_C_default_value)=declarator.value(); #else // is it a type or not? cpp_declarator_converter.is_typedef=declaration.get_bool(ID_is_type); // say it a template parameter cpp_declarator_converter.is_template_parameter=true; // There might be a default type or default value. // We store it for later, as it can't be typechecked now // because of possible dependencies on earlier parameters! exprt default_value=declarator.value(); declarator.value().make_nil(); const symbolt &symbol= cpp_declarator_converter.convert(declaration, declarator); if(cpp_declarator_converter.is_typedef) { parameter=exprt(ID_type, typet(ID_symbol)); parameter.type().set(ID_identifier, symbol.name); parameter.type().add_source_location()=declaration.find_location(); } else parameter=symbol.symbol_expr(); // set (non-typechecked) default value if(default_value.is_not_nil()) parameter.add(ID_C_default_value)=default_value; parameter.add_source_location()=declaration.find_location(); #endif } // continue without adding to the prefix template_scope.prefix=template_scope.get_parent().prefix; return template_scope; }
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::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); } }