示例#1
0
void goto_inlinet::replace_return(
  goto_programt &dest,
  const exprt &lhs,
  const exprt &constrain)
{
  for(goto_programt::instructionst::iterator
      it=dest.instructions.begin();
      it!=dest.instructions.end();
      it++)
  {
    if(it->is_return())
    {
      if(lhs.is_not_nil())
      {
        goto_programt tmp;
        goto_programt::targett assignment=tmp.add_instruction(ASSIGN);
        
        const code_return2t &ret = to_code_return2t(it->code);
        code_assignt code_assign(lhs, migrate_expr_back(ret.operand));

        // this may happen if the declared return type at the call site
        // differs from the defined return type
        if(code_assign.lhs().type()!=
           code_assign.rhs().type())
          code_assign.rhs().make_typecast(code_assign.lhs().type());

        migrate_expr(code_assign, assignment->code);
        assignment->location=it->location;
        assignment->local_variables=it->local_variables;
        assignment->function=it->location.get_function();

        
        assert(constrain.is_nil()); // bp_constrain gumpf reomved
        
        dest.insert_swap(it, *assignment);
        it++;
      }
      else if(!is_nil_expr(it->code))
      {
        // Encode evaluation of return expr, so that returns with pointer
        // derefs in them still get dereferenced, even when the result is
        // discarded.
        goto_programt tmp;
        goto_programt::targett expression=tmp.add_instruction(OTHER);
        
        expression->make_other();
        expression->location=it->location;
        expression->function=it->location.get_function();
        expression->local_variables=it->local_variables;
        const code_return2t &ret = to_code_return2t(it->code);
        expression->code = code_expression2tc(ret.operand);

        dest.insert_swap(it, *expression);
        it++;
      }

      it->make_goto(--dest.instructions.end());
    }
  }
}
示例#2
0
void goto_checkt::add_guarded_claim(const exprt &_expr,
    const std::string &comment, const std::string &property,
    const locationt &location, const guardt &guard)
{
  bool all_claims = options.get_bool_option("all-claims");
  exprt expr(_expr);

  // first try simplifier on it
  if (!options.get_bool_option("no-simplify"))
  {
    expr2tc tmpexpr;
    migrate_expr(expr, tmpexpr);
    base_type(tmpexpr, ns);
    expr = migrate_expr_back(tmpexpr);
    simplify(expr);
  }

  if (!all_claims && expr.is_true())
    return;

  // add the guard
  exprt guard_expr = migrate_expr_back(guard.as_expr());

  exprt new_expr;

  if (guard_expr.is_true())
    new_expr.swap(expr);
  else
  {
    new_expr = exprt("=>", bool_typet());
    new_expr.move_to_operands(guard_expr, expr);
  }

  if (assertions.insert(new_expr).second)
  {
    goto_programt::targett t = new_code.add_instruction(ASSERT);
    migrate_expr(new_expr, t->guard);

    t->location = location;
    t->location.comment(comment);
    t->location.property(property);
  }
}
示例#3
0
void goto_inlinet::parameter_assignments(
  const locationt &location,
  const code_typet &code_type,
  const exprt::operandst &arguments,
  goto_programt &dest)
{
  // iterates over the operands
  exprt::operandst::const_iterator it1=arguments.begin();

  goto_programt::local_variablest local_variables;
  
  const code_typet::argumentst &argument_types=
    code_type.arguments();
  
  // iterates over the types of the arguments
  for(code_typet::argumentst::const_iterator
      it2=argument_types.begin();
      it2!=argument_types.end();
      it2++)
  {
    // if you run out of actual arguments there was a mismatch
    if(it1==arguments.end())
    {
      err_location(location);
      throw "function call: not enough arguments";
    }

    const exprt &argument=static_cast<const exprt &>(*it2);

    // this is the type the n-th argument should be
    const typet &arg_type=ns.follow(argument.type());

    const irep_idt &identifier=argument.cmt_identifier();

    if(identifier=="")
    {
      err_location(location);
      throw "no identifier for function argument";
    }

    {
      const symbolt &symbol=ns.lookup(identifier);

      goto_programt::targett decl=dest.add_instruction();
      decl->make_other();
      exprt tmp = code_declt(symbol_expr(symbol));
      migrate_expr(tmp, decl->code);
      decl->location=location;
      decl->function=location.get_function(); 
      decl->local_variables=local_variables;
    }

    local_variables.insert(identifier);
    
    // nil means "don't assign"
    if(it1->is_nil())
    {    
    }
    else
    {
      // this is the actual parameter
      exprt actual(*it1);

      // it should be the same exact type
      type2tc arg_type_2, actual_type_2;
      migrate_type(arg_type, arg_type_2);
      migrate_type(actual.type(), actual_type_2);
      if (!base_type_eq(arg_type_2, actual_type_2, ns))
      {
        const typet &f_argtype = ns.follow(arg_type);
        const typet &f_acttype = ns.follow(actual.type());
        
        // we are willing to do some conversion
        if((f_argtype.id()=="pointer" &&
            f_acttype.id()=="pointer") ||
           (f_argtype.is_array() &&
            f_acttype.id()=="pointer" &&
            f_argtype.subtype()==f_acttype.subtype()))
        {
          actual.make_typecast(arg_type);
        }
        else if((f_argtype.id()=="signedbv" ||
            f_argtype.id()=="unsignedbv" ||
            f_argtype.is_bool()) &&
           (f_acttype.id()=="signedbv" ||
            f_acttype.id()=="unsignedbv" ||
            f_acttype.is_bool()))  
        {
          actual.make_typecast(arg_type);
        }
        else
        {
          err_location(location);

          str << "function call: argument `" << identifier
              << "' type mismatch: got "
              << from_type(ns, identifier, it1->type())
              << ", expected "
              << from_type(ns, identifier, arg_type);
          throw 0;
        }
      }

      // adds an assignment of the actual parameter to the formal parameter
      code_assignt assignment(symbol_exprt(identifier, arg_type), actual);
      assignment.location()=location;

      dest.add_instruction(ASSIGN);
      dest.instructions.back().location=location;
      migrate_expr(assignment, dest.instructions.back().code);
      dest.instructions.back().local_variables=local_variables;
      dest.instructions.back().function=location.get_function();      
    }

    it1++;
  }

  if(it1!=arguments.end())
  {
    // too many arguments -- we just ignore that, no harm done
  }
}
示例#4
0
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);
    }
  }
}
示例#5
0
void rw_sett::read_write_rec(
  const exprt &expr,
  bool r, bool w,
  const std::string &suffix,
  const guardt &guard)
{
  if(expr.id()=="symbol" && !expr.has_operands())
  {
    const symbol_exprt &symbol_expr=to_symbol_expr(expr);

    const symbolt *symbol;
    if(!ns.lookup(symbol_expr.get_identifier(), symbol))
    {

      if(!symbol->static_lifetime /*&& expr.type().id()=="pointer"*/)
      {
        return; // ignore for now
      }

      if(symbol->name=="c::__ESBMC_alloc" ||
         symbol->name=="c::__ESBMC_alloc_size" ||
         symbol->name=="c::stdin" ||
         symbol->name=="c::stdout" ||
         symbol->name=="c::stderr" ||
         symbol->name=="c::sys_nerr")
      {
        return; // ignore for now
      }
    }

    irep_idt object=id2string(symbol_expr.get_identifier())+suffix;

    entryt &entry=entries[object];
    entry.object=object;
    entry.r=entry.r || r;
    entry.w=entry.w || w;
    entry.guard = migrate_expr_back(guard.as_expr());
  }
  else if(expr.id()=="member")
  {
    assert(expr.operands().size()==1);
    const std::string &component_name=expr.component_name().as_string();
    read_write_rec(expr.op0(), r, w, "."+component_name+suffix, guard);
  }
  else if(expr.id()=="index")
  {
    // we don't distinguish the array elements for now
    assert(expr.operands().size()==2);
    std::string tmp;

    tmp = integer2string(binary2integer(expr.op1().value().as_string(), true),10);

    read_write_rec(expr.op0(), r, w, "["+suffix+tmp+"]", guard);
    read(expr.op1(), guard);
  }
  else if(expr.id()=="dereference")
  {
    assert(expr.operands().size()==1);
    read(expr.op0(), guard);

    exprt tmp(expr.op0());
    expr2tc tmp_expr;
    migrate_expr(tmp, tmp_expr);
    dereference(target, tmp_expr, ns, value_sets);
    tmp = migrate_expr_back(tmp_expr);

    read_write_rec(tmp, r, w, suffix, guard);
  }
  else if(expr.is_address_of() ||
          expr.id()=="implicit_address_of")
  {
    assert(expr.operands().size()==1);

  }
  else if(expr.id()=="if")
  {
    assert(expr.operands().size()==3);
    read(expr.op0(), guard);

    guardt true_guard(guard);
    expr2tc tmp_expr;
    migrate_expr(expr.op0(), tmp_expr);
    true_guard.add(tmp_expr);
    read_write_rec(expr.op1(), r, w, suffix, true_guard);

    guardt false_guard(guard);
    migrate_expr(gen_not(expr.op0()), tmp_expr);
    false_guard.add(tmp_expr);
    read_write_rec(expr.op2(), r, w, suffix, false_guard);
  }
  else
  {
    forall_operands(it, expr)
      read_write_rec(*it, r, w, suffix, guard);
  }
}