Esempio n. 1
0
exprt c_typecheck_baset::do_initializer_list(
  const exprt &value,
  const typet &type,
  bool force_constant)
{
  assert(value.id()==ID_initializer_list);

  if(type.id()==ID_symbol)
    return do_initializer_list(
      value, follow(type), force_constant);

  exprt result;
  if(type.id()==ID_struct ||
     type.id()==ID_array ||
     type.id()==ID_union)
  {
    // start with zero everywhere
    result=zero_initializer(type, value.location());
  }
  else if(type.id()==ID_incomplete_array)
  {
    // start with empty array
    result=exprt(ID_array, type);
    result.location()=value.location();
  }
  else
  {
    // The initializer for a scalar shall be a single expression,
    // * optionally enclosed in braces. *

    if(value.operands().size()==1)
      return do_initializer_rec(value.op0(), type, force_constant);
    
    err_location(value);
    str << "cannot initialize `" << to_string(type) << "' with "
           "an initializer list";
    throw 0;
  }

  designatort current_designator;
  
  designator_enter(type, current_designator);
    
  forall_operands(it, value)
  {
    do_designated_initializer(
      result, current_designator, *it, force_constant);

    // increase designator -- might go up    
    increment_designator(current_designator);
  }
Esempio n. 2
0
void goto_symext::replace_nondet(exprt &expr)
{
  if(expr.id()==ID_sideeffect &&
     expr.get(ID_statement)==ID_nondet)
  {
    exprt new_expr(ID_nondet_symbol, expr.type());
    new_expr.set(ID_identifier, "symex::nondet"+i2string(nondet_count++));
    new_expr.location()=expr.location();
    expr.swap(new_expr);
  }
  else
    Forall_operands(it, expr)
      replace_nondet(*it);
}
Esempio n. 3
0
void c_typecheck_baset::do_designated_initializer(
  exprt &result,
  designatort &designator,
  const exprt &value,
  bool force_constant)
{
  assert(!designator.empty());
  
  if(value.id()==ID_designated_initializer)
  {
    assert(value.operands().size()==1);

    designator=    
      make_designator(
        designator.front().type,
        static_cast<const exprt &>(value.find(ID_designator)));
        
    assert(!designator.empty());
  
    return do_designated_initializer(
      result, designator, value.op0(), force_constant);
  }
  
  exprt *dest=&result;

  // first phase: follow given designator

  for(unsigned i=0; i<designator.size(); i++)
  {
    unsigned index=designator[i].index;
    const typet &type=designator[i].type;
    
    assert(type.id()!=ID_symbol);

    if(type.id()==ID_array ||
       type.id()==ID_struct ||
       type.id()==ID_incomplete_array)
    {
      if(index>=dest->operands().size())
      {
        if(type.id()==ID_incomplete_array)
        {
          exprt zero=zero_initializer(type.subtype(), value.location());
          dest->operands().resize(integer2long(index)+1, zero);
        }
        else
        {
          err_location(value);
          str << "index designator " << index
              << " out of bounds (" << dest->operands().size() << ")";
          throw 0;
        }
      }

      dest=&(dest->operands()[integer2long(index)]);
    }
    else if(type.id()==ID_union)
    {
      // union initialization is quite special
      const union_typet &union_type=to_union_type(type);
      const union_typet::componentt &component=union_type.components()[index];

      // build a union expression from the argument
      exprt union_expr(ID_union, type);
      union_expr.operands().resize(1);
      union_expr.op0()=zero_initializer(component.type(), value.location());
      union_expr.location()=value.location();
      union_expr.set(ID_component_name, component.get_name());

      *dest=union_expr;
      dest=&(dest->op0());
    }
    else
      assert(false);
  }
  
  // second phase: assign value
  // for this, we may need to go down, adding to the designator
  
  while(true)
  {
    // see what type we have to initialize

    typet type=follow(designator.back().subtype);
    assert(type.id()!=ID_symbol);

    // do we initialize a scalar?
    if(type.id()!=ID_struct &&
       type.id()!=ID_union &&
       type.id()!=ID_array &&
       type.id()!=ID_incomplete_array)
    {
      // The initializer for a scalar shall be a single expression,
      // * optionally enclosed in braces. *
      
      if(value.id()==ID_initializer_list &&
         value.operands().size()==1)
        *dest=do_initializer_rec(value.op0(), type, force_constant);
      else
        *dest=do_initializer_rec(value, type, force_constant);

      assert(type==follow(dest->type()));
      
      return; // done
    }

    // see what initializer we are given
    if(value.id()==ID_initializer_list)
    {
      *dest=do_initializer_rec(value, type, force_constant);
      return; // done
    }
    else if(value.id()==ID_string_constant)
    {
      // We stop for initializers that are string-constants,
      // which are like arrays. We only do so if we are to
      // initialize an array of scalars.
      if((type.id()==ID_array || type.id()==ID_incomplete_array) &&
         (follow(type.subtype()).id()==ID_signedbv ||
          follow(type.subtype()).id()==ID_unsignedbv))
      {
        *dest=do_initializer_rec(value, type, force_constant);
        return; // done
      }
    }
    else if(follow(value.type())==type)
    {
      // a struct/union can be initialized directly with
      // an expression of the right type. This doesn't
      // work with arrays, unfortunately.
      if(type.id()==ID_struct || type.id()==ID_union)
      {
        *dest=value;
        return; // done
      }
    }
    
    // we are initializing a compound type, and enter it!
    designator_enter(type, designator);
    
    assert(!dest->operands().empty());
    dest=&(dest->op0());

    // we run into another loop iteration
  }
}
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);
    }