Ejemplo n.º 1
0
void concurrency_instrumentationt::instrument(
  goto_programt &goto_program,
  const is_threadedt &is_threaded)
{
  for(goto_programt::instructionst::iterator
      it=goto_program.instructions.begin();
      it!=goto_program.instructions.end();
      it++)
  {
    if(it->is_assign())
    {
      code_assignt &code=to_code_assign(it->code);
      instrument(code.rhs());
    }
    else if(it->is_assume() || it->is_assert() || it->is_goto())
      instrument(it->guard);
    else if(it->is_function_call())
    {
      code_function_callt &code=to_code_function_call(it->code);
      instrument(code.function());

      //instrument(code.lhs(), LHS);
      Forall_expr(it, code.arguments())
        instrument(*it);
    }
  }
}
Ejemplo n.º 2
0
void havoc_loopst::get_modifies(
  const loopt &loop,
  modifiest &modifies)
{
  for(loopt::const_iterator
      i_it=loop.begin(); i_it!=loop.end(); i_it++)
  {
    const goto_programt::instructiont &instruction=**i_it;

    if(instruction.is_assign())
    {
      const exprt &lhs=to_code_assign(instruction.code).lhs();
      function_modifies.get_modifies_lhs(local_may_alias, *i_it, lhs, modifies);
    }
    else if(instruction.is_function_call())
    {
      const code_function_callt &code_function_call=
        to_code_function_call(instruction.code);
      const exprt &lhs=code_function_call.lhs();

      // return value assignment
      if(lhs.is_not_nil())
        function_modifies.get_modifies_lhs(
          local_may_alias, *i_it, lhs, modifies);

      function_modifies(code_function_call.function(), modifies);
    }
  }
}
Ejemplo n.º 3
0
void local_SSAt::build_transfer(locationt loc)
{
  if(loc->is_assign())
  {
    const code_assignt &code_assign=to_code_assign(loc->code);

    exprt deref_lhs=dereference(code_assign.lhs(), loc);
    exprt deref_rhs=dereference(code_assign.rhs(), loc);

    assign_rec(deref_lhs, deref_rhs, true_exprt(), loc);
  }
  else if(loc->is_function_call())
  {
    const code_function_callt &code_function_call=
      to_code_function_call(loc->code);
      
    const exprt &lhs=code_function_call.lhs();
      
    if(lhs.is_not_nil())
    {
      exprt deref_lhs=dereference(lhs, loc);
    
      // generate a symbol for rhs
      irep_idt identifier="ssa::return_value"+i2string(loc->location_number);
      symbol_exprt rhs(identifier, code_function_call.lhs().type());
      
      assign_rec(deref_lhs, rhs, true_exprt(), loc);
    }
  }
}
Ejemplo n.º 4
0
void cone_of_influencet::cone_of_influence(
  const goto_programt::instructiont &i,
  const expr_sett &curr,
  expr_sett &next)
{
  next.insert(curr.begin(), curr.end());

  if(i.is_assign())
  {
    const code_assignt &assignment=to_code_assign(i.code);
    expr_sett lhs_syms;
    bool care=false;

    gather_rvalues(assignment.lhs(), lhs_syms);

    for(const auto &expr : lhs_syms)
      if(curr.find(expr)!=curr.end())
      {
        care=true;
        break;
      }

    next.erase(assignment.lhs());

    if(care)
    {
      gather_rvalues(assignment.rhs(), next);
    }
  }
}
Ejemplo n.º 5
0
void mutex_init_instrumentation(
  const symbol_tablet &symbol_table,
  goto_programt &goto_program,
  typet lock_type)
{
  symbol_tablet::symbolst::const_iterator f_it=
    symbol_table.symbols.find("__CPROVER_set_must");

  if(f_it==symbol_table.symbols.end())
    return;

  Forall_goto_program_instructions(it, goto_program)
  {
    if(it->is_assign())
    {
      const code_assignt &code_assign=
       to_code_assign(it->code);

      if(code_assign.lhs().type()==lock_type)
      {
        goto_programt::targett t=goto_program.insert_after(it);

        code_function_callt call;

        call.function()=f_it->second.symbol_expr();
        call.arguments().resize(2);
        call.arguments()[0]=address_of_exprt(code_assign.lhs());
        call.arguments()[1]=address_of_exprt(string_constantt("mutex-init"));

        t->make_function_call(call);
        t->source_location=it->source_location;
      }
    }
  }
}
Ejemplo n.º 6
0
void polynomial_acceleratort::cone_of_influence(
    goto_programt::instructionst &orig_body,
    exprt &target,
    goto_programt::instructionst &body,
    expr_sett &cone) {
  utils.gather_rvalues(target, cone);

  for (goto_programt::instructionst::reverse_iterator r_it = orig_body.rbegin();
       r_it != orig_body.rend();
       ++r_it) {
    if (r_it->is_assign()) {
      // XXX -- this doesn't work if the assignment is not to a symbol, e.g.
      // A[i] = 0;
      // or
      // *p = x;
      code_assignt assignment = to_code_assign(r_it->code);
      expr_sett lhs_syms;

      utils.gather_rvalues(assignment.lhs(), lhs_syms);

      for (expr_sett::iterator s_it = lhs_syms.begin();
           s_it != lhs_syms.end();
           ++s_it) {
        if (cone.find(*s_it) != cone.end()) {
          // We're assigning to something in the cone of influence -- expand the
          // cone.
          body.push_front(*r_it);
          cone.erase(assignment.lhs());
          utils.gather_rvalues(assignment.rhs(), cone);
          break;
        }
      }
    }
  }
}
Ejemplo n.º 7
0
void function_modifiest::get_modifies(
  const local_may_aliast &local_may_alias,
  const goto_programt::const_targett i_it,
  modifiest &modifies)
{
  const goto_programt::instructiont &instruction=*i_it;

  if(instruction.is_assign())
  {
    const exprt &lhs=to_code_assign(instruction.code).lhs();
    get_modifies_lhs(local_may_alias, i_it, lhs, modifies);
  }
  else if(instruction.is_function_call())
  {
    const code_function_callt &code_function_call=
      to_code_function_call(instruction.code);
    const exprt &lhs=code_function_call.lhs();

    // return value assignment
    if(lhs.is_not_nil())
      get_modifies_lhs(local_may_alias, i_it, lhs, modifies);

    get_modifies_function(
      code_function_call.function(), modifies);
  }
}
void java_bytecode_typecheckt::typecheck_code(codet &code)
{
  const irep_idt &statement=code.get_statement();

  if(statement==ID_assign)
  {
    code_assignt &code_assign=to_code_assign(code);
    typecheck_expr(code_assign.lhs());
    typecheck_expr(code_assign.rhs());

    if(code_assign.lhs().type()!=code_assign.rhs().type())
      code_assign.rhs().make_typecast(code_assign.lhs().type());
  }
  else if(statement==ID_block)
  {
    Forall_operands(it, code)
      typecheck_code(to_code(*it));
  }
  else if(statement==ID_label)
  {
    code_labelt &code_label=to_code_label(code);
    typecheck_code(code_label.code());
  }
  else if(statement==ID_goto)
  {
  }
  else if(statement==ID_ifthenelse)
  {
    code_ifthenelset &code_ifthenelse=to_code_ifthenelse(code);
    typecheck_expr(code_ifthenelse.cond());
    typecheck_code(code_ifthenelse.then_case());
    if(code_ifthenelse.else_case().is_not_nil())
      typecheck_code(code_ifthenelse.else_case());
  }
  else if(statement==ID_switch)
  {
    code_switcht &code_switch = to_code_switch(code);
    typecheck_expr(code_switch.value());
  }
  else if(statement==ID_return)
  {
    if(code.operands().size()==1)
      typecheck_expr(code.op0());
  }
  else if(statement==ID_function_call)
  {
    code_function_callt &code_function_call=to_code_function_call(code);
    typecheck_expr(code_function_call.lhs());
    typecheck_expr(code_function_call.function());

    for(code_function_callt::argumentst::iterator
        a_it=code_function_call.arguments().begin();
        a_it!=code_function_call.arguments().end();
        a_it++)
      typecheck_expr(*a_it);
  }
}
Ejemplo n.º 9
0
void insert_solution(control_programt &program,
    const control_solutiont &solution)
{
  goto_functionst &gf=program.gf;
  goto_programt &init=get_body(gf, CPROVER_INIT);
  const goto_programt::targett pos=get_solution_assignment(init);
  const symbol_tablet &st=program.st;
  const source_locationt &loc=pos->source_location;
  to_code_assign(pos->code).rhs()=to_struct_expr(st, solution, loc);
}
Ejemplo n.º 10
0
void interval_domaint::transform(
  locationt from,
  locationt to,
  ai_baset &ai,
  const namespacet &ns)
{
  const goto_programt::instructiont &instruction=*from;
  switch(instruction.type)
  {
  case DECL:
    havoc_rec(to_code_decl(instruction.code).symbol());
    break;

  case DEAD:
    havoc_rec(to_code_dead(instruction.code).symbol());
    break;

  case ASSIGN:
    assign(to_code_assign(instruction.code));
    break;

  case GOTO:
    {
      locationt next=from;
      next++;
      if(next==to)
        assume(not_exprt(instruction.guard), ns);
      else
        assume(instruction.guard, ns);
    }
    break;

  case ASSUME:
    assume(instruction.guard, ns);
    break;

  case FUNCTION_CALL:
    {
      const code_function_callt &code_function_call=
        to_code_function_call(instruction.code);
      if(code_function_call.lhs().is_not_nil())
        havoc_rec(code_function_call.lhs());
    }
    break;

  default:
    {
    }
  }
}
Ejemplo n.º 11
0
const typet &get_affected_type(const goto_programt::instructiont &instr)
{
  switch (instr.type)
  {
  case goto_program_instruction_typet::DECL:
    return to_code_decl(instr.code).symbol().type();
  case goto_program_instruction_typet::ASSIGN:
    return to_code_assign(instr.code).lhs().type();
  case goto_program_instruction_typet::DEAD:
    return to_code_dead(instr.code).symbol().type();
  default:
    assert(!"Only DECL, ASSIGN, DEAD allowed.");
  }
}
Ejemplo n.º 12
0
const irep_idt &get_affected_variable(const goto_programt::instructiont &instr)
{
  switch (instr.type)
  {
  case goto_program_instruction_typet::DECL:
    return to_code_decl(instr.code).get_identifier();
  case goto_program_instruction_typet::ASSIGN:
    return to_symbol_expr(to_code_assign(instr.code).lhs()).get_identifier();
  case goto_program_instruction_typet::DEAD:
    return to_code_dead(instr.code).get_identifier();
  default:
    assert(!"Only DECL, ASSIGN, DEAD allowed.");
  }
}
Ejemplo n.º 13
0
bool is_nondet(goto_programt::const_targett target,
    goto_programt::const_targett end)
{
  const goto_programt::instructiont &instr=*target;
  switch (instr.type)
  {
  case goto_program_instruction_typet::DECL:
  {
    goto_programt::const_targett next=std::next(target);
    if (next == end) return true;
    if (goto_program_instruction_typet::FUNCTION_CALL == next->type)
    {
      if (to_code_function_call(next->code).lhs().is_not_nil()) return false;
      else ++next;
    }
    const goto_programt::instructiont next_instr=*next;
    if (goto_program_instruction_typet::ASSIGN != next_instr.type) return true;
    const irep_idt id(get_affected_variable(instr));
    if (id != get_affected_variable(next_instr)) return true;
    return contains(to_code_assign(next_instr.code).rhs(), id);
  }
  case goto_program_instruction_typet::ASSIGN:
  {
    const exprt &rhs=to_code_assign(instr.code).rhs();
    if (ID_side_effect != rhs.id()) return false;
    return ID_nondet == to_side_effect_expr(rhs).get_statement();
  }
  case goto_program_instruction_typet::FUNCTION_CALL:
  {
    const code_function_callt &call=to_code_function_call(instr.code);
    if (call.lhs().is_not_nil()) return false;
  }
  default:
    return false;
  }
}
Ejemplo n.º 14
0
void nondet_static(
  const namespacet &ns,
  goto_functionst &goto_functions,
  const irep_idt &fct_name)
{
  goto_functionst::function_mapt::iterator
    i_it=goto_functions.function_map.find(fct_name);
  assert(i_it!=goto_functions.function_map.end());

  goto_programt &init=i_it->second.body;

  Forall_goto_program_instructions(i_it, init)
  {
    const goto_programt::instructiont &instruction=*i_it;

    if(instruction.is_assign())
    {
      const symbol_exprt &sym=to_symbol_expr(
          to_code_assign(instruction.code).lhs());

      // is it a __CPROVER_* variable?
      if(has_prefix(id2string(sym.get_identifier()), CPROVER_PREFIX))
        continue;
        
      // static lifetime?
      if(!ns.lookup(sym.get_identifier()).is_static_lifetime)
        continue;

      // constant?
      if(sym.type().get_bool(ID_C_constant))
        continue;

      i_it=init.insert_before(++i_it);
      i_it->make_assignment();
      i_it->code=code_assignt(sym, side_effect_expr_nondett(sym.type()));
      i_it->location=instruction.location;
      i_it->function=instruction.function;
    }
    else if(instruction.is_function_call())
    {
      const code_function_callt &fct=to_code_function_call(instruction.code);
      const symbol_exprt &fsym=to_symbol_expr(fct.function());

      if(has_prefix(id2string(fsym.get_identifier()), "c::#ini#"))
        nondet_static(ns, goto_functions, fsym.get_identifier());
    }
  }
}
Ejemplo n.º 15
0
void jsil_typecheckt::typecheck_code(codet &code)
{
  const irep_idt &statement=code.get_statement();

  if(statement==ID_function_call)
    typecheck_function_call(to_code_function_call(code));
  else if(statement==ID_return)
    typecheck_return(to_code_return(code));
  else if(statement==ID_expression)
  {
    if(code.operands().size()!=1)
      throw "expression statement expected to have one operand";

    typecheck_expr(code.op0());
  }
  else if(statement==ID_label)
  {
    typecheck_code(to_code_label(code).code());
    // TODO: produce defined label set
  }
  else if(statement==ID_block)
    typecheck_block(code);
  else if(statement==ID_ifthenelse)
    typecheck_ifthenelse(to_code_ifthenelse(code));
  else if(statement==ID_goto)
  {
    // TODO: produce used label set
  }
  else if(statement==ID_assign)
    typecheck_assign(to_code_assign(code));
  else if(statement==ID_try_catch)
    typecheck_try_catch(to_code_try_catch(code));
  else if(statement==ID_skip)
  {
  }
  else
  {
    err_location(code);
    error() << "unexpected statement: " << statement << eom;
    throw 0;
  }
}
Ejemplo n.º 16
0
void k_inductiont::get_modifies(
  const loopt &loop,
  modifiest &modifies)
{
  for(loopt::const_iterator
      i_it=loop.begin(); i_it!=loop.end(); i_it++)
  {
    const goto_programt::instructiont &instruction=**i_it;

    if(instruction.is_assign())
    {
      const exprt &lhs=to_code_assign(instruction.code).lhs();
      get_modifies_lhs(*i_it, lhs, modifies);
    }
    else if(instruction.is_function_call())
    {
      const exprt &lhs=to_code_function_call(instruction.code).lhs();
      get_modifies_lhs(*i_it, lhs, modifies);
    }
  }
}
Ejemplo n.º 17
0
void interpretert::execute_assign()
{
  const code_assignt &code_assign=
    to_code_assign(PC->code);

  std::vector<mp_integer> rhs;
  evaluate(code_assign.rhs(), rhs);
  
  if(!rhs.empty())
  {
    mp_integer address=evaluate_address(code_assign.lhs());  
    unsigned size=get_size(code_assign.lhs().type());

    if(size!=rhs.size())
      std::cout << "!! failed to obtain rhs ("
                << rhs.size() << " vs. "
                << size << ")" << std::endl;
    else
      assign(address, rhs);
  }
}
Ejemplo n.º 18
0
goto_tracet::stepst::const_iterator termination_baset::get_loop(
  goto_tracet &trace)
{
  if(trace.steps.size()<3)
    throw "counterexample is too short";

  const goto_trace_stept &assertion=trace.steps.back();

  assert(assertion.is_assert());

  goto_tracet::stepst::const_iterator step=--trace.steps.end();

  // skip over assertion
  step--;

  // we need to see the copy-instruction at least once.
  assert(assertion.pc->guard.operands().size()==2);
  const irep_idt my_id=assertion.pc->guard.op0().get("identifier");
  bool seen_copy=false;

  while(step->pc!=assertion.pc || !seen_copy)
  {
    if(step==trace.steps.begin()) // failed
      throw "failed to find beginning of loop";

    if(step->pc->type==ASSIGN)
    {
      const code_assignt &code=to_code_assign(step->pc->code);
      if(code.lhs().id()=="symbol" &&
         code.lhs().get("identifier")==my_id)
        seen_copy=true;
    }

    step--;
  }

  // found it!
  return step;
}
Ejemplo n.º 19
0
exprt polynomial_acceleratort::precondition(patht &path) {
  exprt ret = false_exprt();

  for (patht::reverse_iterator r_it = path.rbegin();
       r_it != path.rend();
       ++r_it) {
    goto_programt::const_targett t = r_it->loc;

    if (t->is_assign()) {
      // XXX Need to check for aliasing...
      const code_assignt &assignment = to_code_assign(t->code);
      const exprt &lhs = assignment.lhs();
      const exprt &rhs = assignment.rhs();

      if (lhs.id() == ID_symbol) {
        replace_expr(lhs, rhs, ret);
      } else if (lhs.id() == ID_index ||
                 lhs.id() == ID_dereference) {
        continue;
      } else {
        throw "Couldn't take WP of " + expr2c(lhs, ns) + " = " + expr2c(rhs, ns);
      }
    } else if (t->is_assume() || t->is_assert()) {
      ret = implies_exprt(t->guard, ret);
    } else {
      // Ignore.
    }

    if (!r_it->guard.is_true() && !r_it->guard.is_nil()) {
      // The guard isn't constant true, so we need to accumulate that too.
      ret = implies_exprt(r_it->guard, ret);
    }
  }

  simplify(ret, ns);

  return ret;
}
Ejemplo n.º 20
0
void rd_range_domaint::transform(
  const namespacet &ns,
  locationt from,
  locationt to)
{
  if(from->is_dead())
  {
    const symbol_exprt &symbol=
      to_symbol_expr(to_code_dead(from->code).symbol());
    values.erase(symbol.get_identifier());
    return;
  }
  else if(!from->is_assign())
    return;

  const exprt &lhs=to_code_assign(from->code).lhs();

  if(lhs.id()==ID_complex_real ||
          lhs.id()==ID_complex_imag)
  {
    assert(lhs.type().id()==ID_complex);
    mp_integer offset=compute_pointer_offset(ns, lhs.op0());
    mp_integer sub_size=pointer_offset_size(ns, lhs.type().subtype());

    assign(
      ns,
      from,
      lhs.op0(),
      offset+((offset==-1 || lhs.id()==ID_complex_real) ? 0 : sub_size),
      sub_size);
  }
  else
  {
    mp_integer size=pointer_offset_size(ns, lhs.type());

    assign(ns, from, lhs, size);
  }
}
Ejemplo n.º 21
0
void termination_baset::find_required_steps(
  const goto_tracet &goto_trace,
  goto_tracet::stepst::const_iterator &loop_begin,
  required_stepst &required_steps,
  const std::string &prefix) const
{
  find_symbols_sett required_symbols;
  unsigned before=0, after=1;

  // initialize: find all (potential) loop exits and
  // remember the symbols in them
  for(goto_tracet::stepst::const_iterator it1=loop_begin;
      it1!=goto_trace.steps.end();
      it1++)
  {
    if(it1->pc->is_goto() &&
       it1->pc->function==loop_begin->pc->function)
    {
      bool found_next=false, found_target=false;
      goto_programt::const_targett next=it1->pc; next++;
      goto_programt::const_targett target=it1->pc->targets.front();

      for(goto_tracet::stepst::const_iterator it2=loop_begin;
          it2!=goto_trace.steps.end();
          it2++)
      {
        if(it1!=it2)
        {
          if(it2->pc==next)
            found_next=true;
          else if(it2->pc==target)
            found_target=true;
        }
      }

      if(!found_target || !found_next)
      {
        exprt temp=it1->cond_expr;
        remove_ssa_ids(temp);
        find_symbols(temp, required_symbols);
      }
    }
  }

  #if 0
  std::cout << "INITIAL SYMBOLS: ";
  for(find_symbols_sett::const_iterator it=required_symbols.begin();
      it!=required_symbols.end();
      it++)
    std::cout << *it << ", ";
  std::cout << std::endl;
  #endif

  // get the fixpoint
  while(before!=after)
  {
    before=required_symbols.size();

    for(goto_tracet::stepst::const_iterator step=loop_begin;
        step!=goto_trace.steps.end();
        step++)
    {
      find_symbols_sett intersection;

      if(step->is_assignment())
      {
        exprt lhs, rhs;

        const codet &code=to_code(step->pc->code);

        if(code.get_statement()==ID_assign)
        {
          const code_assignt &acode=to_code_assign(step->pc->code);
          lhs=acode.lhs();
          rhs=acode.rhs();
        }
        else if(code.get_statement()==ID_function_call)
        {
          const code_function_callt fcode=to_code_function_call(step->pc->code);
          lhs=fcode.lhs();
          rhs=fcode.op2();
        }
        else
          throw "Unexpected assign statement";

        if(lhs.id()==ID_symbol &&
           has_prefix(lhs.get_string(ID_identifier), prefix))
        {
          // if we depend on the RHS syms, we also need the pre-symbol
          find_symbols_sett rhs_sym;
          find_symbols(rhs, rhs_sym);

          if(intersects(rhs_sym, required_symbols))
          {
            find_symbols(lhs, required_symbols);
            required_steps.insert(&(*step));
          }
        }
        else
        {
          find_symbols_sett lhs_sym;

          if(lhs.id()==ID_index)
            find_symbols(lhs.op0(), lhs_sym); // we're not modifying the index
          else
            find_symbols(lhs, lhs_sym);

           if(intersects(lhs_sym, required_symbols))
           {
             find_symbols(rhs, required_symbols);
             required_steps.insert(&(*step));
           }
        }
      }
      else if(step->is_assume())
      {
        find_symbols_sett syms;
        find_symbols(step->pc->guard, syms);

        if(intersects(syms, required_symbols))
        {
          required_symbols.insert(syms.begin(), syms.end());
          required_steps.insert(&(*step));
        }
      }
    }

    after=required_symbols.size();

  #if 0
  std::cout << "REQUIRED SYMBOLS: ";
  for(find_symbols_sett::const_iterator it=required_symbols.begin();
      it!=required_symbols.end();
      it++)
    std::cout << *it << ", ";
  std::cout << std::endl;
  #endif
  }
}
Ejemplo n.º 22
0
bodyt termination_baset::get_body(
  goto_tracet::stepst::const_iterator &loop_begin,
  const goto_tracet &trace)
{
  bodyt result_body;
  exprt::operandst op;
  const goto_trace_stept &assertion=trace.steps.back();

  // let's get a loop number as well:
  assert(assertion.pc->guard.id()=="=>");
  std::string c_str = assertion.pc->guard.op0().get_string("identifier");
  std::string prefix = termination_prefix+
                       c_str.substr(c_str.rfind("_")+1) + "::";

  // find out what we actually need
  required_stepst required_steps;
  find_required_steps(trace, loop_begin, required_steps, prefix);

  /* We perform a new SSA-conversion. However, since we can only
     get a single path through the program, there are no joins and
     thus no phi-functions. We just increment counters. */

  std::map<irep_idt, unsigned> ssa_counters;
  replace_idt replace_id;

  // get the required body constraints
  for(goto_tracet::stepst::const_iterator step=loop_begin;
      step!=--trace.steps.end();
      step++)
  {
    last_path.push_back(step->pc);

    // required_stepst::const_iterator fit=required_steps.find(&(*step));
    // if(fit==required_steps.end()) continue;

    switch(step->pc->type)
    {
      case ASSIGN:
      {
        const code_assignt &code=to_code_assign(step->pc->code);
        find_symbols_sett w;
        find_symbols_w(code.lhs(), w);

        equal_exprt equality(code.lhs(), code.rhs());
        replace_id.replace(equality.rhs());

        // All the written ones get their SSA-ID updated
        for(find_symbols_sett::const_iterator it=w.begin();
            it!=w.end();
            it++)
        {
          // Are we writing a pre-variable?
          if(has_prefix(id2string(*it), prefix))
          {
            assert(code.rhs().id()==ID_symbol);
            const irep_idt &post_id=code.rhs().get(ID_identifier);
            const irep_idt &pre_id=code.lhs().get(ID_identifier);
            result_body.variable_map[post_id]=pre_id;

            // the RHS gets a #0 id
            irep_idt new_id=id2string(post_id)+"!0";
            replace_id.insert(post_id, new_id);
            equality.rhs().set(ID_identifier, new_id);
          }
          else
          {
            const irep_idt &old_id=*it;
            unsigned cur=++ssa_counters[old_id]; // 0 is never used

            // gets a new ID
            irep_idt new_id=id2string(old_id)+"!"+i2string(cur);
            replace_id.insert(old_id, new_id);
          }
        }

        replace_id.replace(equality.lhs());
        op.push_back(equality);
        break;
      }
      case ASSUME:
      case ASSERT:
      {
        if(!step->cond_expr.is_true() && !step->cond_expr.is_nil())
        {
          exprt guard=step->cond_expr; // That's SSA!
          remove_ssa_ids(guard);
//          exprt guard=step->pc->guard;

          find_symbols_sett syms;
          find_symbols(guard, syms);

          for(find_symbols_sett::const_iterator it=syms.begin();
              it!=syms.end();
              it++)
          {
            if(ssa_counters.find(*it)==ssa_counters.end())
            {
              irep_idt new_id=id2string(*it)+"!"+i2string(++ssa_counters[*it]);
              replace_id.insert(*it, new_id);
            }
          }

          replace_id.replace(guard);
          if(!step->cond_value) guard.negate();
          op.push_back(guard);
        }
        break;
      }
      case GOTO:
      {
        if(!step->cond_expr.is_nil())
        {
//          exprt guard=step->pc->guard;
          exprt guard=step->cond_expr;
          remove_ssa_ids(guard);

          find_symbols_sett syms;
          find_symbols(guard, syms);

          for(find_symbols_sett::const_iterator it=syms.begin();
              it!=syms.end();
              it++)
          {
            if(ssa_counters.find(*it)==ssa_counters.end())
            {
              ssa_counters[*it]=0;
              irep_idt new_id=id2string(*it)+"!"+i2string(0);
              replace_id.insert(*it, new_id);
            }
          }

          replace_id.replace(guard);
          if(!step->cond_value)
            guard.negate();
          op.push_back(guard);
        }
        break;
      }
      case DECL: /* nothing */ break;
	    case LOCATION: /* These can show up here? */ break;
      default:
        throw std::string("unexpected instruction type.");
    }
  }

  // the final result, which (again) contains SSA variables
  exprt &body_expr = result_body.body_relation;
  body_expr = and_exprt(op);

  if(result_body.variable_map.empty())
  {
    // used to be:
    // throw "BUG: No variables found; path missing.";
    // Though: No variable is ever saved, i.e., this loop
    // must be completely nondeterministic.
    warning("No pre-variables found; this "
            "loop is completely non-deterministic.");
    body_expr=false_exprt();
  }

  // The last SSA-occurrence of a variable is the
  // output variable and it gets its non-SSA name.
  replace_idt last_map;
  for(std::map<irep_idt, unsigned>::const_iterator it=ssa_counters.begin();
      it!=ssa_counters.end();
      it++)
  {
    const irep_idt &id=it->first;
    unsigned last=it->second;

    irep_idt last_name=id2string(id)+"!"+i2string(last);
    last_map.insert(last_name, id);
  }

  last_map.replace(body_expr);

  replace_nondet_sideeffects(body_expr);

  return result_body;
}
Ejemplo n.º 23
0
void goto_symext::symex_step(
  const goto_functionst &goto_functions,
  statet &state)
{
  #if 0
  std::cout << "\ninstruction type is " << state.source.pc->type << '\n';
  std::cout << "Location: " << state.source.pc->source_location << '\n';
  std::cout << "Guard: " << from_expr(ns, "", state.guard.as_expr()) << '\n';
  std::cout << "Code: " << from_expr(ns, "", state.source.pc->code) << '\n';
  #endif

  assert(!state.threads.empty());
  assert(!state.call_stack().empty());

  const goto_programt::instructiont &instruction=*state.source.pc;

  merge_gotos(state);

  // depth exceeded?
  {
    unsigned max_depth=options.get_unsigned_int_option("depth");
    if(max_depth!=0 && state.depth>max_depth)
      state.guard.add(false_exprt());
    state.depth++;
  }

  // actually do instruction
  switch(instruction.type)
  {
  case SKIP:
    if(!state.guard.is_false())
      target.location(state.guard.as_expr(), state.source);
    state.source.pc++;
    break;

  case END_FUNCTION:
    // do even if state.guard.is_false() to clear out frame created
    // in symex_start_thread
    symex_end_of_function(state);
    state.source.pc++;
    break;

  case LOCATION:
    if(!state.guard.is_false())
      target.location(state.guard.as_expr(), state.source);
    state.source.pc++;
    break;

  case GOTO:
    symex_goto(state);
    break;

  case ASSUME:
    if(!state.guard.is_false())
    {
      exprt tmp=instruction.guard;
      clean_expr(tmp, state, false);
      state.rename(tmp, ns);
      symex_assume(state, tmp);
    }

    state.source.pc++;
    break;

  case ASSERT:
    if(!state.guard.is_false())
    {
      std::string msg=id2string(state.source.pc->source_location.get_comment());
      if(msg=="")
        msg="assertion";
      exprt tmp(instruction.guard);
      clean_expr(tmp, state, false);
      vcc(tmp, msg, state);
    }

    state.source.pc++;
    break;

  case RETURN:
    if(!state.guard.is_false())
      return_assignment(state);

    state.source.pc++;
    break;

  case ASSIGN:
    if(!state.guard.is_false())
      symex_assign_rec(state, to_code_assign(instruction.code));

    state.source.pc++;
    break;

  case FUNCTION_CALL:
    if(!state.guard.is_false())
    {
      code_function_callt deref_code=
        to_code_function_call(instruction.code);

      if(deref_code.lhs().is_not_nil())
        clean_expr(deref_code.lhs(), state, true);

      clean_expr(deref_code.function(), state, false);

      Forall_expr(it, deref_code.arguments())
        clean_expr(*it, state, false);

      symex_function_call(goto_functions, state, deref_code);
    }
    else
      state.source.pc++;
    break;

  case OTHER:
    if(!state.guard.is_false())
      symex_other(goto_functions, state);

    state.source.pc++;
    break;

  case DECL:
    if(!state.guard.is_false())
      symex_decl(state);

    state.source.pc++;
    break;

  case DEAD:
    symex_dead(state);
    state.source.pc++;
    break;

  case START_THREAD:
    symex_start_thread(state);
    state.source.pc++;
    break;

  case END_THREAD:
    // behaves like assume(0);
    if(!state.guard.is_false())
      state.guard.add(false_exprt());
    state.source.pc++;
    break;

  case ATOMIC_BEGIN:
    symex_atomic_begin(state);
    state.source.pc++;
    break;

  case ATOMIC_END:
    symex_atomic_end(state);
    state.source.pc++;
    break;

  case CATCH:
    symex_catch(state);
    state.source.pc++;
    break;

  case THROW:
    symex_throw(state);
    state.source.pc++;
    break;

  case NO_INSTRUCTION_TYPE:
    throw "symex got NO_INSTRUCTION";

  default:
    throw "symex got unexpected instruction";
  }
}
Ejemplo n.º 24
0
void goto_inlinet::expand_function_call(
  goto_programt &dest,
  goto_programt::targett &target,
  const exprt &lhs,
  const symbol_exprt &function,
  const exprt::operandst &arguments,
  const exprt &constrain,
  bool full)
{
  // look it up
  const irep_idt identifier=function.get_identifier();
  
  // we ignore certain calls
  if(identifier=="__CPROVER_cleanup" ||
     identifier=="__CPROVER_set_must" ||
     identifier=="__CPROVER_set_may" ||
     identifier=="__CPROVER_clear_must" ||
     identifier=="__CPROVER_clear_may" ||
     identifier=="__CPROVER_cover")
  {
    target++;
    return; // ignore
  }
  
  // see if we are already expanding it
  if(recursion_set.find(identifier)!=recursion_set.end())
  {
    if(!full)
    {
      target++;
      return; // simply ignore, we don't do full inlining, it's ok
    }

    // it's really recursive, and we need full inlining.
    // Uh. Buh. Give up.
    warning().source_location=function.find_source_location();
    warning() << "recursion is ignored" << eom;
    target->make_skip();
    
    target++;
    return;
  }

  goto_functionst::function_mapt::iterator m_it=
    goto_functions.function_map.find(identifier);

  if(m_it==goto_functions.function_map.end())
  {
    if(!full)
    {
      target++;
      return; // simply ignore, we don't do full inlining, it's ok
    }

    error().source_location=function.find_source_location();
    error() << "failed to find function `" << identifier << "'" << eom;
    throw 0;
  }
  
  const goto_functionst::goto_functiont &f=m_it->second;

  // see if we need to inline this  
  if(!full)
  {
    if(!f.body_available() ||
       (!f.is_inlined() && f.body.instructions.size() > smallfunc_limit))
    {
      target++;
      return;
    }
  }

  if(f.body_available())
  {
    recursion_set.insert(identifier);

    // first make sure that this one is already inlined
    goto_inline_rec(m_it, full);

    goto_programt tmp2;
    tmp2.copy_from(f.body);
    
    assert(tmp2.instructions.back().is_end_function());
    tmp2.instructions.back().type=LOCATION;
    
    replace_return(tmp2, lhs, constrain);

    goto_programt tmp;
    parameter_assignments(target->source_location, identifier, f.type, arguments, tmp);
    tmp.destructive_append(tmp2);
    parameter_destruction(target->source_location, identifier, f.type, tmp);

    if(f.is_hidden())
    {
      source_locationt new_source_location=
        function.find_source_location();
    
      if(new_source_location.is_not_nil())
      {
        new_source_location.set_hide();
      
        Forall_goto_program_instructions(it, tmp)
        {
          if(it->function==identifier)
          {
            // don't hide assignment to lhs
            if(it->is_assign() && to_code_assign(it->code).lhs()==lhs)
            {
            }
            else
            {
              replace_location(it->source_location, new_source_location);
              replace_location(it->guard, new_source_location);
              replace_location(it->code, new_source_location);
            }

            it->function=target->function;
          }
        }
      }
Ejemplo n.º 25
0
void goto_checkt::goto_check(goto_functiont &goto_function)
{
  {
    const symbolt *init_symbol;
    if(!ns.lookup(CPROVER_PREFIX "initialize", init_symbol))
      mode=init_symbol->mode;
  }

  assertions.clear();

  local_bitvector_analysist local_bitvector_analysis_obj(goto_function);
  local_bitvector_analysis=&local_bitvector_analysis_obj;

  goto_programt &goto_program=goto_function.body;

  Forall_goto_program_instructions(it, goto_program)
  {
    t=it;
    goto_programt::instructiont &i=*it;

    new_code.clear();

    // we clear all recorded assertions if
    // 1) we want to generate all assertions or
    // 2) the instruction is a branch target
    if(retain_trivial ||
       i.is_target())
      assertions.clear();

    check(i.guard);

    // magic ERROR label?
    for(optionst::value_listt::const_iterator
        l_it=error_labels.begin();
        l_it!=error_labels.end();
        l_it++)
    {
      if(std::find(i.labels.begin(), i.labels.end(), *l_it)!=i.labels.end())
      {
        goto_program_instruction_typet type=
          enable_assert_to_assume?ASSUME:ASSERT;

        goto_programt::targett t=new_code.add_instruction(type);

        t->guard=false_exprt();
        t->source_location=i.source_location;
        t->source_location.set_property_class("error label");
        t->source_location.set_comment("error label "+*l_it);
        t->source_location.set("user-provided", true);
      }
    }

    if(i.is_other())
    {
      const irep_idt &statement=i.code.get(ID_statement);

      if(statement==ID_expression)
      {
        check(i.code);
      }
      else if(statement==ID_printf)
      {
        forall_operands(it, i.code)
          check(*it);
      }
    }
    else if(i.is_assign())
    {
      const code_assignt &code_assign=to_code_assign(i.code);

      check(code_assign.lhs());
      check(code_assign.rhs());

      // the LHS might invalidate any assertion
      invalidate(code_assign.lhs());
    }
    else if(i.is_function_call())
    {
      const code_function_callt &code_function_call=
        to_code_function_call(i.code);

      // for Java, need to check whether 'this' is null
      // on non-static method invocations
      if(mode==ID_java &&
         enable_pointer_check &&
         !code_function_call.arguments().empty() &&
         code_function_call.function().type().id()==ID_code &&
         to_code_type(code_function_call.function().type()).has_this())
      {
        exprt pointer=code_function_call.arguments()[0];

        local_bitvector_analysist::flagst flags=
          local_bitvector_analysis->get(t, pointer);

        if(flags.is_unknown() || flags.is_null())
        {
          notequal_exprt not_eq_null(pointer, gen_zero(pointer.type()));

          add_guarded_claim(
            not_eq_null,
            "this is null on method invokation",
            "pointer dereference",
            i.source_location,
            pointer,
            guardt());
        }
      }

      forall_operands(it, code_function_call)
        check(*it);

      // the call might invalidate any assertion
      assertions.clear();
    }
    else if(i.is_return())
    {
      if(i.code.operands().size()==1)
      {
        check(i.code.op0());
        // the return value invalidate any assertion
        invalidate(i.code.op0());
      }
    }
    else if(i.is_throw())
    {
      if(i.code.get_statement()==ID_expression &&
         i.code.operands().size()==1 &&
         i.code.op0().operands().size()==1)
      {
        // must not throw NULL

        exprt pointer=i.code.op0().op0();

        if(pointer.type().subtype().get(ID_identifier)!="java::java.lang.AssertionError")
        {
          notequal_exprt not_eq_null(pointer, gen_zero(pointer.type()));

          add_guarded_claim(
            not_eq_null,
            "throwing null",
            "pointer dereference",
            i.source_location,
            pointer,
            guardt());
        }
      }

      // this has no successor
      assertions.clear();
    }
    else if(i.is_assert())
    {
      if(i.source_location.get_bool("user-provided") &&
         i.source_location.get_property_class()!="error label" &&
         !enable_assertions)
        i.type=SKIP;
    }
    else if(i.is_assume())
    {
      if(!enable_assumptions)
        i.type=SKIP;
    }
    else if(i.is_dead())
    {
      if(enable_pointer_check)
      {
        assert(i.code.operands().size()==1);
        const symbol_exprt &variable=to_symbol_expr(i.code.op0());

        // is it dirty?
        if(local_bitvector_analysis->dirty(variable))
        {
          // need to mark the dead variable as dead
          goto_programt::targett t=new_code.add_instruction(ASSIGN);
          exprt address_of_expr=address_of_exprt(variable);
          exprt lhs=ns.lookup(CPROVER_PREFIX "dead_object").symbol_expr();
          if(!base_type_eq(lhs.type(), address_of_expr.type(), ns))
            address_of_expr.make_typecast(lhs.type());
          exprt rhs=if_exprt(
            side_effect_expr_nondett(bool_typet()), address_of_expr, lhs, lhs.type());
          t->source_location=i.source_location;
          t->code=code_assignt(lhs, rhs);
          t->code.add_source_location()=i.source_location;
        }
      }
    }
    else if(i.is_end_function())
    {
      if(i.function==goto_functionst::entry_point() &&
         enable_memory_leak_check)
      {
        const symbolt &leak=ns.lookup(CPROVER_PREFIX "memory_leak");
        const symbol_exprt leak_expr=leak.symbol_expr();

        // add self-assignment to get helpful counterexample output
        goto_programt::targett t=new_code.add_instruction();
        t->make_assignment();
        t->code=code_assignt(leak_expr, leak_expr);

        source_locationt source_location;
        source_location.set_function(i.function);

        equal_exprt eq(leak_expr, gen_zero(ns.follow(leak.type)));
        add_guarded_claim(
          eq,
          "dynamically allocated memory never freed",
          "memory-leak",
          source_location,
          eq,
          guardt());
      }
    }

    for(goto_programt::instructionst::iterator
        i_it=new_code.instructions.begin();
        i_it!=new_code.instructions.end();
        i_it++)
    {
      if(i_it->source_location.is_nil())
      {
        i_it->source_location.id(irep_idt());

        if(it->source_location.get_file()!=irep_idt())
          i_it->source_location.set_file(it->source_location.get_file());

        if(it->source_location.get_line()!=irep_idt())
          i_it->source_location.set_line(it->source_location.get_line());

        if(it->source_location.get_function()!=irep_idt())
          i_it->source_location.set_function(it->source_location.get_function());

        if(it->source_location.get_column()!=irep_idt())
          i_it->source_location.set_column(it->source_location.get_column());
      }

      if(i_it->function==irep_idt()) i_it->function=it->function;
    }

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

    while(!new_code.instructions.empty())
    {
      goto_program.insert_before_swap(it, new_code.instructions.front());
      new_code.instructions.pop_front();
      it++;
    }
  }
Ejemplo n.º 26
0
bool refiner_wpt::refine_prefix(
  predicatest &predicates, 
  abstract_modelt &abstract_model,
  const fail_infot &fail_info)
{
  status("Refining set of predicates according to counterexample (WP)");

  reset_num_predicates_added();

  bool found_new=false;

  // keep track of the loops that we're in (may be nested)
  std::list<fail_infot::induction_infot> loops;
  exprt invariant;
  if(fail_info.use_invariants)
    status("Using recurrence predicates detected by loop detection.");
  
  print(10, "refiner_wpt::refine_prefix_async 1");
  
  print(10, "Inconsistent prefix:");

  for(abstract_counterexamplet::stepst::const_reverse_iterator 
      r_it=fail_info.steps.rbegin();
      r_it!=fail_info.steps.rend();
      r_it++)
  {
    std::stringstream str;

    abstract_programt::targett abstract_pc=r_it->pc;

    goto_programt::const_targett concrete_pc=
      abstract_pc->code.concrete_pc;

    if(concrete_pc->is_goto())
      str << "GUARD: " << (r_it->branch_taken?"(":"!(")
                << from_expr(concrete_model.ns, "", concrete_pc->guard) << ")";
    else if(concrete_pc->is_assert())
      str << "ASSERT: "
                << from_expr(concrete_model.ns, "", concrete_pc->guard);
    else if(concrete_pc->is_location())
      str << "LOC" << std::endl;
    else if(concrete_pc->is_other() || concrete_pc->is_assign() || concrete_pc->is_decl())
      str << from_expr(concrete_model.ns, "", concrete_pc->code);
    else
    {
      str << concrete_pc->type;
    }

    str << "  // " << (concrete_pc->location);

    str << std::endl << "**********";

    print(10, str.str());
  }

  
  {
    // get the constraint causing the failure

    exprt predicate=fail_info.guard;

    #ifdef DEBUG
    std::cout << "P start0: " 
              << from_expr(concrete_model.ns, "", predicate) << std::endl;
    #endif

    simplify(predicate, concrete_model.ns);

    abstract_counterexamplet::stepst::const_iterator 
      it=--fail_info.steps.end();

    // there must be at least two steps, or it's odd
    assert(it!=fail_info.steps.begin());

    {
      abstract_programt::targett abstract_pc=it->pc;

      #ifdef DEBUG
      std::cout << "P start1: " 
                << from_expr(concrete_model.ns, "", predicate) << std::endl;
      #endif

      add_predicates(
        abstract_pc, predicates, predicate, found_new, FROM);
    }
      
    // now do the WPs
    goto_symex_statet renaming_state;
    renaming_state.source.thread_nr=it->thread_nr;
    renaming_state.rename(predicate, concrete_model.ns, goto_symex_statet::L0);

    for(it--; // skip last instruction
        it!=fail_info.steps.begin();
        it--)
    {
      #ifdef DEBUG
      std::cout << "refiner_wpt::refine_prefix_async 2\n";
      #endif

      // handle loops 
      if(fail_info.use_invariants)
      {
        if(it->is_loop_begin())
        {
          loops.pop_back(); // pop induction_info if we leave loop
          
#ifdef DEBUG
          std::cout << "INV: "
                    << from_expr(concrete_model.ns, "", invariant) << std::endl;
#endif           
          
          exprt wp(ID_and, typet(ID_bool));
          wp.operands().resize(2);
          wp.op0().swap(invariant);
          wp.op1().swap(predicate);
          predicate.swap(wp);
        }
        else if (it->is_loop_end())
        {
          push_induction_info(fail_info, it, loops);
          invariant.make_true();
        }
      }

      if(!it->is_state())
        continue;

      if(predicate.is_true() && found_new)
      {
        // ok, refuted it, done
        break;
      }
        
      // add the predicate

      goto_programt::const_targett concrete_pc=
        it->pc->code.concrete_pc;
        
      abstract_programt::targett abstract_pc=it->pc;
        
      #ifdef DEBUG
      std::cout << from_expr(concrete_model.ns, "", predicate) << std::endl;
      #endif
      
      exprt no_tid_predicate=predicate;
      renaming_state.get_original_name(no_tid_predicate);
      add_predicates(abstract_pc, predicates, no_tid_predicate, found_new, TO);

      // skip irrelevant instructions
      if(!it->relevant) continue;

      exprt pred_bak=predicate;
#ifdef DEBUG
      goto_programt tmp;
      tmp.output_instruction(concrete_model.ns, "", std::cerr, concrete_pc);
#endif

      // compute weakest precondition
      switch(it->pc->type)
      {
      case ASSUME:
        // we only do this for assumptions
        // if we haven't found a new predicate so far
        if(1/*!found_new*/)
        {
          exprt tid_guard=concrete_pc->guard;
          renaming_state.source.thread_nr=it->thread_nr;
          renaming_state.rename(tid_guard, concrete_model.ns, goto_symex_statet::L0);
          predicate=implies_exprt(tid_guard, predicate);
          simplify(predicate, concrete_model.ns);
        }
        break;

      case GOTO:
        {
          exprt tid_guard=concrete_pc->guard;
          if(!it->branch_taken) tid_guard.make_not();
          renaming_state.source.thread_nr=it->thread_nr;
          renaming_state.rename(tid_guard, concrete_model.ns, goto_symex_statet::L0);
          predicate=implies_exprt(tid_guard, predicate);
          simplify(predicate, concrete_model.ns);
        }
        break;

      case OTHER:
    	/* Ignore if user-specified predicate, otherwise treat like assign */
    	if(it->pc->code.concrete_pc->code.get_statement()==ID_user_specified_predicate || it->pc->code.concrete_pc->code.get_statement()==ID_user_specified_parameter_predicates || it->pc->code.concrete_pc->code.get_statement()==ID_user_specified_return_predicates)
    		break;
      case DECL:
      case ASSIGN:
        #ifdef DEBUG
        std::cout << "OTHER/ASSIGN/DECL\n";
        #endif

        {
          codet tid_tmp_code;
          if(!fail_info.use_invariants ||
             !get_instruction(concrete_pc, loops, tid_tmp_code, invariant))
            tid_tmp_code=to_code(concrete_pc->code);

#ifdef DEBUG
          std::cout << "A P before: " << from_expr(concrete_model.ns, "", predicate) << std::endl;
          std::cout << "Code:     " << from_expr(concrete_model.ns, "", tid_tmp_code) << std::endl;
#endif
          
          // compute weakest precondition
          if(tid_tmp_code.get_statement()==ID_assign)
            approximate_nondet(to_code_assign(tid_tmp_code).rhs());
          renaming_state.source.thread_nr=it->thread_nr;
          renaming_state.rename(tid_tmp_code, concrete_model.ns, goto_symex_statet::L0);
          exprt predicate_wp=wp(tid_tmp_code, predicate, concrete_model.ns);
      
          simplify(predicate_wp, concrete_model.ns);
          predicate=predicate_wp;

#ifdef DEBUG
          std::cout << "A P after:  " << from_expr(concrete_model.ns, "", predicate) << std::endl;
#endif
        }
        break;

      default:
        // ignore
        break;
      }

#ifdef DEBUG
          std::cout << "B P to-check:  " << from_expr(concrete_model.ns, "", predicate) << std::endl;
#endif
          
      if(pred_bak != predicate)
      {
        satcheckt satcheck;
        bv_pointerst solver(concrete_model.ns, satcheck);
        solver.unbounded_array=boolbvt::U_NONE;
        literalt li=make_pos(concrete_model.ns, solver, predicate);
        satcheck.set_assumptions(bvt(1, li));
        propt::resultt result=satcheck.prop_solve();
        assert(propt::P_SATISFIABLE==result || propt::P_UNSATISFIABLE==result);
        if(propt::P_UNSATISFIABLE==result)
          predicate.make_false();
        else
        {
          satcheck.set_assumptions(bvt(1, li.negation()));
          propt::resultt result=satcheck.prop_solve();
          assert(propt::P_SATISFIABLE==result || propt::P_UNSATISFIABLE==result);
          if(propt::P_UNSATISFIABLE==result)
          {
            predicate.make_true();
            if(it->pc->type==ASSIGN)
            {
              const codet &code=concrete_pc->code;
              if(code.get_statement()==ID_assign)
              {
                equal_exprt pred_new(to_code_assign(code).lhs(),
                    to_code_assign(code).rhs());
                simplify(pred_new, concrete_model.ns);
#ifdef DEBUG
                std::cout << "Adding new predicate as we arrived at TRUE: "
                  << from_expr(concrete_model.ns, "", pred_new) << std::endl;
#endif
                no_tid_predicate=pred_new;
                renaming_state.get_original_name(no_tid_predicate);
                add_predicates(abstract_pc, predicates, no_tid_predicate, found_new, FROM);
              }
            }
            else if(it->pc->type==ASSUME || it->pc->type==GOTO)
            {
              exprt pred_new=concrete_pc->guard;
              simplify(pred_new, concrete_model.ns);
#ifdef DEBUG
              std::cout << "Adding new predicate as we arrived at TRUE: "
                << from_expr(concrete_model.ns, "", pred_new) << std::endl;
#endif
              no_tid_predicate=pred_new;
              renaming_state.get_original_name(no_tid_predicate);
              add_predicates(abstract_pc, predicates, no_tid_predicate, found_new, FROM);
            }
          }
        }
      }
      
      #ifdef DEBUG
      std::cout << "B P after:   " << from_expr(concrete_model.ns, "", predicate) << std::endl;
      #endif

      no_tid_predicate=predicate;
      renaming_state.get_original_name(no_tid_predicate);
      add_predicates(abstract_pc, predicates, no_tid_predicate, found_new, FROM);
    }

    if(!predicate.is_true() && fail_info.warn_on_failure)
    {
      warning("Failed to refute spurious trace with WPs (got "+
              from_expr(concrete_model.ns, "", predicate)+")");
    }
  }

  if(found_new && fail_info.use_invariants)
  {
    add_induction_predicates(
      fail_info,
      abstract_model,
      predicates);
  }
  
  // make sure we have progress
  return !found_new;
}
Ejemplo n.º 27
0
void invariant_set_domaint::transform(
  locationt from_l,
  locationt to_l,
  ai_baset &ai,
  const namespacet &ns)
{
  switch(from_l->type)
  {
  case GOTO:
    {
      exprt tmp(from_l->guard);

      goto_programt::const_targett next=from_l;
      next++;
      if(next==to_l)
        tmp.make_not();

      simplify(tmp, ns);
      invariant_set.strengthen(tmp);
    }
    break;

  case ASSERT:
  case ASSUME:
    {
      exprt tmp(from_l->guard);
      simplify(tmp, ns);
      invariant_set.strengthen(tmp);
    }
    break;

  case RETURN:
    // ignore
    break;

  case ASSIGN:
    {
      const code_assignt &assignment=to_code_assign(from_l->code);
      invariant_set.assignment(assignment.lhs(), assignment.rhs());
    }
    break;

  case OTHER:
    if(from_l->code.is_not_nil())
      invariant_set.apply_code(from_l->code);
    break;

  case DECL:
    invariant_set.apply_code(from_l->code);
    break;

  case FUNCTION_CALL:
    invariant_set.apply_code(from_l->code);
    break;

  case START_THREAD:
    invariant_set.make_threaded();
    break;

  default:
    {
      // do nothing
    }
  }
}