예제 #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::goto_check(goto_programt &goto_program)
{
  for (goto_programt::instructionst::iterator it =
      goto_program.instructions.begin(); it != goto_program.instructions.end();
      it++)
  {
    goto_programt::instructiont &i = *it;

    new_code.clear();
    assertions.clear();

    check(migrate_expr_back(i.guard));

    if (i.is_other())
    {
      if (is_code_expression2t(i.code))
      {
        check(migrate_expr_back(i.code));
      }
      else if (is_code_printf2t(i.code))
      {
        i.code->foreach_operand([this] (const expr2tc &e) {
          check(migrate_expr_back(e));
          }
        );
      }
    }
    else if (i.is_assign())
    {
      const code_assign2t &assign = to_code_assign2t(i.code);
      check(migrate_expr_back(assign.target));
      check(migrate_expr_back(assign.source));
    }
    else if (i.is_function_call())
    {
      i.code->foreach_operand([this] (const expr2tc &e) {
        check(migrate_expr_back(e));
        }
      );
    }
    else if (i.is_return())
    {
      const code_return2t &ret = to_code_return2t(i.code);
      check(migrate_expr_back(ret.operand));
    }

    for (goto_programt::instructionst::iterator i_it =
        new_code.instructions.begin(); i_it != new_code.instructions.end();
        i_it++)
    {
      i_it->local_variables = it->local_variables;
      if (i_it->location.is_nil())
      {
        if (!i_it->location.comment().as_string().empty())
          it->location.comment(i_it->location.comment());
        if (!i_it->location.property().as_string().empty())
          it->location.property(i_it->location.property());

        i_it->location = it->location;
      }
      if (i_it->function == "")
        i_it->function = it->function;
      if (i_it->function == "")
        i_it->function = it->function;
    }

    // insert new instructions -- make sure targets are not moved

    while (!new_code.instructions.empty())
    {
      goto_program.insert_swap(it, new_code.instructions.front());
      new_code.instructions.pop_front();
      it++;
    }
  }
}