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); }