void goto_symext::symex_other( const goto_functionst &goto_functions, statet &state) { const goto_programt::instructiont &instruction=*state.source.pc; const codet &code=to_code(instruction.code); const irep_idt &statement=code.get_statement(); if(statement==ID_expression) { // ignore } else if(statement==ID_cpp_delete || statement=="cpp_delete[]") { codet clean_code=code; clean_expr(clean_code, state, false); symex_cpp_delete(state, clean_code); } else if(statement==ID_free) { // ignore } else if(statement==ID_printf) { codet clean_code=code; clean_expr(clean_code, state, false); symex_printf(state, nil_exprt(), clean_code); } else if(statement==ID_input) { codet clean_code(code); clean_expr(clean_code, state, false); symex_input(state, clean_code); } else if(statement==ID_output) { codet clean_code(code); clean_expr(clean_code, state, false); symex_output(state, clean_code); } else if(statement==ID_decl) { assert(false); // see symex_decl.cpp } else if(statement==ID_nondet) { // like skip } else if(statement==ID_asm) { // we ignore this for now } else if(statement==ID_array_copy) { assert(code.operands().size()==2); codet clean_code(code); // we need to add dereferencing for both operands dereference_exprt d0, d1; d0.op0()=code.op0(); d0.type()=code.op0().type().subtype(); d1.op0()=code.op1(); d1.type()=code.op1().type().subtype(); clean_code.op0()=d0; clean_code.op1()=d1; clean_expr(clean_code, state, false); process_array_expr(clean_code.op0()); process_array_expr(clean_code.op1()); if(ns.follow(clean_code.op0().type()).id()!=ID_array) throw "array_copy expects array operand"; if(!base_type_eq(clean_code.op0().type(), clean_code.op1().type(), ns)) throw "array_copy expects matching array types"; code_assignt assignment; assignment.lhs()=clean_code.op0(); assignment.rhs()=clean_code.op1(); basic_symext::symex_assign(state, assignment); } else if(statement==ID_array_set) { assert(code.operands().size()==2); codet clean_code(code); // we need to add dereferencing for the first operand dereference_exprt d0; d0.op0()=code.op0(); d0.type()=code.op0().type().subtype(); clean_code.op0()=d0; clean_expr(clean_code, state, false); process_array_expr(clean_code.op0()); const typet &array_type=ns.follow(clean_code.op0().type()); if(array_type.id()!=ID_array) throw "array_set expects array operand"; if(!base_type_eq(array_type.subtype(), clean_code.op1().type(), ns)) clean_code.op1().make_typecast(array_type.subtype()); code_assignt assignment; assignment.lhs()=clean_code.op0(); assignment.rhs()=array_of_exprt(clean_code.op1(), clean_code.op0().type()); basic_symext::symex_assign(state, assignment); } else if(statement==ID_user_specified_predicate || statement==ID_user_specified_parameter_predicates || statement == ID_user_specified_return_predicates) { // like skip } else throw "unexpected statement: "+id2string(statement); }
void goto_symext::symex_other() { const goto_programt::instructiont &instruction = *cur_state->source.pc; expr2tc code2 = instruction.code; if(is_code_expression2t(code2)) { // Represents an expression that gets evaluated, but does not have any // other effect on execution, i.e. doesn't contain a call or assignment. // This can, however, cause the program to fail if it dereferences an // invalid pointer. Therefore, dereference it. const code_expression2t &expr = to_code_expression2t(code2); expr2tc operand = expr.operand; dereference(operand, dereferencet::READ); } else if(is_code_cpp_del_array2t(code2) || is_code_cpp_delete2t(code2)) { expr2tc deref_code(code2); replace_dynamic_allocation(deref_code); replace_nondet(deref_code); dereference(deref_code, dereferencet::READ); symex_cpp_delete(deref_code); } else if(is_code_free2t(code2)) { symex_free(code2); } else if(is_code_printf2t(code2)) { replace_dynamic_allocation(code2); replace_nondet(code2); dereference(code2, dereferencet::READ); symex_printf(expr2tc(), code2); } else if(is_code_decl2t(code2)) { replace_dynamic_allocation(code2); replace_nondet(code2); dereference(code2, dereferencet::READ); const code_decl2t &decl_code = to_code_decl2t(code2); // just do the L2 renaming to preseve locality const irep_idt &identifier = decl_code.value; // Generate dummy symbol as a vehicle for renaming. symbol2tc l1_sym(get_empty_type(), identifier); cur_state->top().level1.get_ident_name(l1_sym); symbol2t &l1_symbol = to_symbol2t(l1_sym); // increase the frame if we have seen this declaration before while(cur_state->top().declaration_history.find( renaming::level2t::name_record(l1_symbol)) != cur_state->top().declaration_history.end()) { unsigned &index = cur_state->variable_instance_nums[identifier]; cur_state->top().level1.rename(l1_sym, ++index); l1_symbol.level1_num = index; } renaming::level2t::name_record tmp_name(l1_symbol); cur_state->top().declaration_history.insert(tmp_name); cur_state->top().local_variables.insert(tmp_name); // seen it before? // it should get a fresh value if(cur_state->level2.current_number(l1_sym) != 0) { // Dummy assignment - blank constant value isn't considered for const // propagation, variable number will be bumped to result in a new free // variable. Invalidates l1_symbol reference? cur_state->level2.make_assignment(l1_sym, expr2tc(), expr2tc()); } } else if(is_code_asm2t(code2)) { // Assembly statement -> do nothing. return; } else throw "goto_symext: unexpected statement: " + get_expr_id(code2); }