void goto_program_dereferencet::dereference_rec( exprt &expr, guardt &guard, const value_set_dereferencet::modet mode) { if(!dereference.has_dereference(expr)) return; if(expr.id()==ID_and || expr.id()==ID_or) { if(!expr.is_boolean()) throw expr.id_string()+" must be Boolean, but got "+ expr.pretty(); unsigned old_guards=guard.size(); for(unsigned i=0; i<expr.operands().size(); i++) { exprt &op=expr.operands()[i]; if(!op.is_boolean()) throw expr.id_string()+" takes Boolean operands only, but got "+ op.pretty(); if(dereference.has_dereference(op)) dereference_rec(op, guard, value_set_dereferencet::READ); if(expr.id()==ID_or) { exprt tmp(op); tmp.make_not(); guard.add(tmp); } else guard.add(op); } guard.resize(old_guards); return; } else if(expr.id()==ID_if) { if(expr.operands().size()!=3) throw "if takes three arguments"; if(!expr.op0().is_boolean()) { std::string msg= "first argument of if must be boolean, but got " +expr.op0().to_string(); throw msg; } dereference_rec(expr.op0(), guard, value_set_dereferencet::READ); bool o1=dereference.has_dereference(expr.op1()); bool o2=dereference.has_dereference(expr.op2()); if(o1) { unsigned old_guard=guard.size(); guard.add(expr.op0()); dereference_rec(expr.op1(), guard, mode); guard.resize(old_guard); } if(o2) { unsigned old_guard=guard.size(); exprt tmp(expr.op0()); tmp.make_not(); guard.add(tmp); dereference_rec(expr.op2(), guard, mode); guard.resize(old_guard); } return; } if(expr.id()==ID_address_of || expr.id()=="reference_to") { // turn &*p to p // this has *no* side effect! assert(expr.operands().size()==1); if(expr.op0().id()==ID_dereference || expr.op0().id()=="implicit_dereference") { assert(expr.op0().operands().size()==1); exprt tmp; tmp.swap(expr.op0().op0()); if(tmp.type()!=expr.type()) tmp.make_typecast(expr.type()); expr.swap(tmp); } } Forall_operands(it, expr) dereference_rec(*it, guard, mode); if(expr.id()==ID_dereference) { if(expr.operands().size()!=1) throw "dereference expects one operand"; dereference_location=expr.find_location(); exprt tmp=dereference.dereference( expr.op0(), guard, mode); expr.swap(tmp); } else if(expr.id()=="implicit_dereference") { // old stuff assert(false); } else if(expr.id()==ID_index) { // this is old stuff and will go away if(expr.operands().size()!=2) throw "index expects two operands"; if(expr.op0().type().id()==ID_pointer) { dereference_location=expr.find_location(); exprt tmp1(ID_plus, expr.op0().type()); tmp1.operands().swap(expr.operands()); exprt tmp2=dereference.dereference(tmp1, guard, mode); tmp2.swap(expr); } } }
void goto_checkt::check_rec(const exprt &expr, guardt &guard, bool address) { if (address) { if (expr.id() == "dereference") { assert(expr.operands().size() == 1); check_rec(expr.op0(), guard, false); } else if (expr.id() == "index") { assert(expr.operands().size() == 2); check_rec(expr.op0(), guard, true); check_rec(expr.op1(), guard, false); } else { forall_operands(it, expr) check_rec(*it, guard, true); } return; } if (expr.is_address_of()) { assert(expr.operands().size() == 1); check_rec(expr.op0(), guard, true); return; } else if (expr.is_and() || expr.id() == "or") { if (!expr.is_boolean()) throw expr.id_string() + " must be Boolean, but got " + expr.pretty(); unsigned old_guards = guard.size(); for (unsigned i = 0; i < expr.operands().size(); i++) { const exprt &op = expr.operands()[i]; if (!op.is_boolean()) throw expr.id_string() + " takes Boolean operands only, but got " + op.pretty(); check_rec(op, guard, false); if (expr.id() == "or") { exprt tmp(op); tmp.make_not(); expr2tc tmp_expr; migrate_expr(tmp, tmp_expr); guard.move(tmp_expr); } else { expr2tc tmp; migrate_expr(op, tmp); guard.add(tmp); } } guard.resize(old_guards); return; } else if (expr.id() == "if") { if (expr.operands().size() != 3) throw "if takes three arguments"; if (!expr.op0().is_boolean()) { std::string msg = "first argument of if must be boolean, but got " + expr.op0().to_string(); throw msg; } check_rec(expr.op0(), guard, false); { unsigned old_guard = guard.size(); expr2tc tmp; migrate_expr(expr.op0(), tmp); guard.add(tmp); check_rec(expr.op1(), guard, false); guard.resize(old_guard); } { unsigned old_guard = guard.size(); exprt tmp(expr.op0()); tmp.make_not(); expr2tc tmp_expr; migrate_expr(tmp, tmp_expr); guard.move(tmp_expr); check_rec(expr.op2(), guard, false); guard.resize(old_guard); } return; } forall_operands(it, expr) check_rec(*it, guard, false); if (expr.id() == "index") { bounds_check(expr, guard); } else if (expr.id() == "/") { div_by_zero_check(expr, guard); if (expr.type().id() == "signedbv") { overflow_check(expr, guard); } else if (expr.type().id() == "floatbv") { nan_check(expr, guard); } } else if (expr.id() == "+" || expr.id() == "-" || expr.id() == "*" || expr.id() == "unary-" || expr.id() == "typecast") { if (expr.type().id() == "signedbv") { overflow_check(expr, guard); } else if (expr.type().id() == "floatbv") { nan_check(expr, guard); } } else if (expr.id() == "<=" || expr.id() == "<" || expr.id() == ">=" || expr.id() == ">") { pointer_rel_check(expr, guard); } else if (expr.id() == "mod") { div_by_zero_check(expr, guard); if (expr.type().id() == "signedbv") { overflow_check(expr, guard); } else if (expr.type().id() == "floatbv") { nan_check(expr, guard); } } }