void c_typecheck_baset::typecheck_decl(codet &code) { // this comes with 1 operand, which is a declaration if(code.operands().size()!=1) { err_location(code); error() << "decl expected to have 1 operand" << eom; throw 0; } // op0 must be declaration if(code.op0().id()!=ID_declaration) { err_location(code); error() << "decl statement expected to have declaration as operand" << eom; throw 0; } ansi_c_declarationt declaration; declaration.swap(code.op0()); if(declaration.get_is_static_assert()) { assert(declaration.operands().size()==2); codet new_code(ID_static_assert); new_code.add_source_location()=code.source_location(); new_code.operands().swap(declaration.operands()); code.swap(new_code); typecheck_code(code); return; // done } typecheck_declaration(declaration); std::list<codet> new_code; // iterate over declarators for(ansi_c_declarationt::declaratorst::const_iterator d_it=declaration.declarators().begin(); d_it!=declaration.declarators().end(); d_it++) { irep_idt identifier=d_it->get_name(); // look it up symbol_tablet::symbolst::iterator s_it= symbol_table.symbols.find(identifier); if(s_it==symbol_table.symbols.end()) { err_location(code); error() << "failed to find decl symbol `" << identifier << "' in symbol table" << eom; throw 0; } symbolt &symbol=s_it->second; // This must not be an incomplete type, unless it's 'extern' // or a typedef. if(!symbol.is_type && !symbol.is_extern && !is_complete_type(symbol.type)) { error().source_location=symbol.location; error() << "incomplete type not permitted here" << eom; throw 0; } // see if it's a typedef // or a function // or static if(symbol.is_type || symbol.type.id()==ID_code || symbol.is_static_lifetime) { // we ignore } else { code_declt code; code.add_source_location()=symbol.location; code.symbol()=symbol.symbol_expr(); code.symbol().add_source_location()=symbol.location; // add initializer, if any if(symbol.value.is_not_nil()) { code.operands().resize(2); code.op1()=symbol.value; } new_code.push_back(code); } } // stash away any side-effects in the declaration new_code.splice(new_code.begin(), clean_code); if(new_code.empty()) { source_locationt source_location=code.source_location(); code=code_skipt(); code.add_source_location()=source_location; } else if(new_code.size()==1) { code.swap(new_code.front()); } else { // build a decl-block code_blockt code_block(new_code); code_block.set_statement(ID_decl_block); code.swap(code_block); } }
void c_typecheck_baset::typecheck_for(codet &code) { if(code.operands().size()!=4) { err_location(code); error() << "for expected to have four operands" << eom; throw 0; } // the "for" statement has an implicit block around it, // since code.op0() may contain declarations // // we therefore transform // // for(a;b;c) d; // // to // // { a; for(;b;c) d; } // // if config.ansi_c.for_has_scope if(!config.ansi_c.for_has_scope || code.op0().is_nil()) { if(code.op0().is_not_nil()) typecheck_code(to_code(code.op0())); if(code.op1().is_nil()) code.op1()=true_exprt(); else { typecheck_expr(code.op1()); implicit_typecast_bool(code.op1()); } if(code.op2().is_not_nil()) typecheck_expr(code.op2()); if(code.op3().is_not_nil()) { // save & set flags bool old_break_is_allowed=break_is_allowed; bool old_continue_is_allowed=continue_is_allowed; break_is_allowed=continue_is_allowed=true; // recursive call if(to_code(code.op3()).get_statement()==ID_decl_block) { code_blockt code_block; code_block.add_source_location()=code.op3().source_location(); code_block.move_to_operands(code.op3()); code.op3().swap(code_block); } typecheck_code(to_code(code.op3())); // restore flags break_is_allowed=old_break_is_allowed; continue_is_allowed=old_continue_is_allowed; } } else { code_blockt code_block; code_block.add_source_location()=code.source_location(); if(to_code(code.op3()).get_statement()==ID_block) code_block.set( ID_C_end_location, to_code_block(to_code(code.op3())).end_location()); else code_block.set( ID_C_end_location, code.op3().source_location());; code_block.reserve_operands(2); code_block.move_to_operands(code.op0()); code.op0().make_nil(); code_block.move_to_operands(code); code.swap(code_block); typecheck_code(code); // recursive call } typecheck_spec_expr(code, ID_C_spec_loop_invariant); }
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); }