void goto_symext::process_array_expr(exprt &expr) { // This may change the type of the expression! if(expr.id()==ID_if) { if_exprt &if_expr=to_if_expr(expr); process_array_expr(if_expr.true_case()); process_array_expr_rec(if_expr.false_case(), if_expr.true_case().type()); if_expr.type()=if_expr.true_case().type(); } else if(expr.id()==ID_index) { // strip index index_exprt &index_expr=to_index_expr(expr); exprt tmp=index_expr.array(); expr.swap(tmp); } else if(expr.id()==ID_typecast) { // strip exprt tmp=to_typecast_expr(expr).op0(); expr.swap(tmp); process_array_expr(expr); } else if(expr.id()==ID_address_of) { // strip exprt tmp=to_address_of_expr(expr).op0(); expr.swap(tmp); process_array_expr(expr); } else if(expr.id()==ID_symbol && expr.get_bool(ID_C_SSA_symbol) && to_ssa_expr(expr).get_original_expr().id()==ID_index) { const ssa_exprt &ssa=to_ssa_expr(expr); const index_exprt &index_expr=to_index_expr(ssa.get_original_expr()); exprt tmp=index_expr.array(); expr.swap(tmp); } else Forall_operands(it, expr) process_array_expr(*it); }
void goto_symext::replace_array_equal(exprt &expr) { if(expr.id()==ID_array_equal) { assert(expr.operands().size()==2); // we expect two index expressions process_array_expr(expr.op0()); process_array_expr(expr.op1()); // type checking if(ns.follow(expr.op0().type())!= ns.follow(expr.op1().type())) expr=false_exprt(); else { equal_exprt equality_expr(expr.op0(), expr.op1()); expr.swap(equality_expr); } } Forall_operands(it, expr) replace_array_equal(*it); }
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); }