Ejemplo n.º 1
0
void goto_convertt::clean_expr(
  exprt &expr,
  goto_programt &dest,
  bool result_is_used)
{
  // this cleans:
  //   && || ?: comma (control-dependency)
  //   function calls
  //   object constructors like arrays, string constants, structs
  //   ++ --
  //   compound assignments
  //   compound literals

  if(!needs_cleaning(expr)) return;

  if(expr.id()==ID_and || expr.id()==ID_or)
  {
    // rewrite into ?:
    rewrite_boolean(expr);
    
    // recursive call
    clean_expr(expr, dest, result_is_used);
    return;
  }
  else if(expr.id()==ID_if)
  {
    // first clean condition
    clean_expr(to_if_expr(expr).cond(), dest, true);

    // possibly done now
    if(!needs_cleaning(to_if_expr(expr).true_case()) &&
       !needs_cleaning(to_if_expr(expr).false_case()))
      return;

    // copy expression
    if_exprt if_expr=to_if_expr(expr);
    
    if(!if_expr.cond().is_boolean())
      throw "first argument of `if' must be boolean, but got "
        +if_expr.cond().to_string();

    const locationt location=expr.find_location();
  
    // We do some constant-folding here, to mimic
    // what typical compilers do.
    {
      exprt tmp_cond=if_expr.cond();
      simplify(tmp_cond, ns);
      if(tmp_cond.is_true())
      {
        clean_expr(if_expr.true_case(), dest, result_is_used);
        expr=if_expr.true_case();
        return;
      }
      else if(tmp_cond.is_false())
      {
        clean_expr(if_expr.false_case(), dest, result_is_used);
        expr=if_expr.false_case();
        return;
      }
    }

    goto_programt tmp_true;
    clean_expr(if_expr.true_case(), tmp_true, result_is_used);

    goto_programt tmp_false;
    clean_expr(if_expr.false_case(), tmp_false, result_is_used);
    
    if(result_is_used)
    {
      symbolt &new_symbol=
        new_tmp_symbol(expr.type(), "if_expr", dest, location);

      code_assignt assignment_true;
      assignment_true.lhs()=new_symbol.symbol_expr();
      assignment_true.rhs()=if_expr.true_case();
      assignment_true.location()=location;
      convert(assignment_true, tmp_true);

      code_assignt assignment_false;
      assignment_false.lhs()=new_symbol.symbol_expr();
      assignment_false.rhs()=if_expr.false_case();
      assignment_false.location()=location;
      convert(assignment_false, tmp_false);

      // overwrites expr
      expr=new_symbol.symbol_expr();
    }
    else
    {
      // preserve the expressions for possible later checks
      if(if_expr.true_case().is_not_nil())
      {
        code_expressiont code_expression(if_expr.true_case());
        convert(code_expression, tmp_true);
      }
      
      if(if_expr.false_case().is_not_nil())
      {
        code_expressiont code_expression(if_expr.false_case());
        convert(code_expression, tmp_false);
      }
      
      expr=nil_exprt();
    }

    // generate guard for argument side-effects    
    generate_ifthenelse(
      if_expr.cond(), tmp_true, tmp_false,
      location, dest);

    return;
  }
  else if(expr.id()==ID_comma)
  {
    if(result_is_used)
    {
      exprt result;
    
      Forall_operands(it, expr)
      {
        bool last=(it==--expr.operands().end());
        
        // special treatment for last one
        if(last)
        {
          result.swap(*it);
          clean_expr(result, dest, true);
        }
        else
        {
          clean_expr(*it, dest, false);

          // remember these for later checks
          if(it->is_not_nil())
            convert(code_expressiont(*it), dest);
        }
      }

      expr.swap(result);
    }
    else // result not used
    {
Ejemplo n.º 2
0
void goto_convertt::clean_expr(
  exprt &expr,
  goto_programt &dest,
  bool result_is_used)
{
  // this cleans:
  //   && || ?: comma (control-dependency)
  //   function calls
  //   object constructors like arrays, string constants, structs
  //   ++ --
  //   compound assignments

  if(!needs_cleaning(expr)) return;

  if(expr.id()==ID_and || expr.id()==ID_or)
  {
    // rewrite into ?:
    rewrite_boolean(expr);
    
    // recursive call
    clean_expr(expr, dest, result_is_used);
    return;
  }
  else if(expr.id()==ID_if)
  {
    if(expr.operands().size()!=3)
      throw "if takes three arguments";

    if(!expr.op0().is_boolean())
      throw "first argument of `if' must be boolean, but got "
        +expr.op0().to_string();

    // first pull out condition -- we need to prevent
    // this getting destroyed by the side-effects in the other
    // operands
    make_temp_symbol(expr.op0(), "condition", dest);

    // now clean arguments    
    goto_programt tmp_true, tmp_false;
    clean_expr(expr.op1(), tmp_true, result_is_used);
    clean_expr(expr.op2(), tmp_false, result_is_used);

    // generate guard for argument side-effects    
    generate_ifthenelse(
      expr.op0(), tmp_true, tmp_false,
      expr.location(), dest);

    return;
  }
  else if(expr.id()==ID_comma)
  {
    exprt result;
  
    Forall_operands(it, expr)
    {
      bool last=(it==--expr.operands().end());
      
      if(last)
      {
        result.swap(*it);
        clean_expr(result, dest, result_is_used);
      }
      else
        clean_expr(*it, dest, false);
    }