Beispiel #1
0
void c_typecheck_baset::typecheck_array_type(array_typet &type)
{
  exprt &size=type.size();
  source_locationt source_location=size.find_source_location();

  // check subtype
  typecheck_type(type.subtype());

  // we don't allow void as subtype
  if(follow(type.subtype()).id()==ID_empty)
  {
    error().source_location=type.source_location();
    error() << "array of voids" << eom;
    throw 0;
  }

  // check size, if any

  if(size.is_not_nil())
  {
    typecheck_expr(size);
    make_index_type(size);

    // The size need not be a constant!
    // We simplify it, for the benefit of array initialisation.

    exprt tmp_size=size;
    add_rounding_mode(tmp_size);
    simplify(tmp_size, *this);

    if(tmp_size.is_constant())
    {
      mp_integer s;
      if(to_integer(tmp_size, s))
      {
        error().source_location=source_location;
        error() << "failed to convert constant: "
                << tmp_size.pretty() << eom;
        throw 0;
      }

      if(s<0)
      {
        error().source_location=source_location;
        error() << "array size must not be negative, "
                   "but got " << s << eom;
        throw 0;
      }

      size=tmp_size;
    }
    else if(tmp_size.id()==ID_infinity)
    {
      size=tmp_size;
    }
    else if(tmp_size.id()==ID_symbol &&
            tmp_size.type().get_bool(ID_C_constant))
    {
      // We allow a constant variable as array size, assuming
      // it won't change.
      // This criterion can be tricked:
      // Of course we can modify a 'const' symbol, e.g.,
      // using a pointer type cast. Interestingly,
      // at least gcc 4.2.1 makes the very same mistake!
      size=tmp_size;
    }
    else
    {
      // not a constant and not infinity

      assert(current_symbol_id!=irep_idt());

      const symbolt &base_symbol=lookup(current_symbol_id);

      // Need to pull out! We insert new symbol.
      source_locationt source_location=size.find_source_location();
      unsigned count=0;
      irep_idt temp_identifier;
      std::string suffix;

      do
      {
        suffix="$array_size"+std::to_string(count);
        temp_identifier=id2string(base_symbol.name)+suffix;
        count++;
      }
      while(symbol_table.symbols.find(temp_identifier)!=
            symbol_table.symbols.end());

      // add the symbol to symbol table
      auxiliary_symbolt new_symbol;
      new_symbol.name=temp_identifier;
      new_symbol.pretty_name=id2string(base_symbol.pretty_name)+suffix;
      new_symbol.base_name=id2string(base_symbol.base_name)+suffix;
      new_symbol.type=size.type();
      new_symbol.type.set(ID_C_constant, true);
      new_symbol.is_type=false;
      new_symbol.is_static_lifetime=false;
      new_symbol.value.make_nil();
      new_symbol.location=source_location;

      symbol_table.add(new_symbol);

      // produce the code that declares and initializes the symbol
      symbol_exprt symbol_expr;
      symbol_expr.set_identifier(temp_identifier);
      symbol_expr.type()=new_symbol.type;

      code_declt declaration(symbol_expr);
      declaration.add_source_location()=source_location;

      code_assignt assignment;
      assignment.lhs()=symbol_expr;
      assignment.rhs()=size;
      assignment.add_source_location()=source_location;

      // store the code
      clean_code.push_back(declaration);
      clean_code.push_back(assignment);

      // fix type
      size=symbol_expr;
    }
  }
}
Beispiel #2
0
void boolbvt::convert_with_array(
  const array_typet &type,
  const exprt &op1,
  const exprt &op2,
  const bvt &prev_bv,
  bvt &next_bv)
{
  if(is_unbounded_array(type))
  {
    // can't do this
    error().source_location=type.source_location();
    error() << "convert_with_array called for unbounded array" << eom;
    throw 0;
  }

  const exprt &array_size=type.size();

  mp_integer size;

  if(to_integer(array_size, size))
  {
    error().source_location=type.source_location();
    error() << "convert_with_array expects constant array size" << eom;
    throw 0;
  }

  const bvt &op2_bv=convert_bv(op2);

  if(size*op2_bv.size()!=prev_bv.size())
  {
    error().source_location=type.source_location();
    error() << "convert_with_array: unexpected operand 2 width" << eom;
    throw 0;
  }

  // Is the index a constant?
  mp_integer op1_value;
  if(!to_integer(op1, op1_value))
  {
    // Yes, it is!
    next_bv=prev_bv;

    if(op1_value>=0 && op1_value<size) // bounds check
    {
      std::size_t offset=integer2unsigned(op1_value*op2_bv.size());

      for(std::size_t j=0; j<op2_bv.size(); j++)
        next_bv[offset+j]=op2_bv[j];
    }

    return;
  }

  typet counter_type=op1.type();

  for(mp_integer i=0; i<size; i=i+1)
  {
    exprt counter=from_integer(i, counter_type);

    literalt eq_lit=convert(equal_exprt(op1, counter));

    std::size_t offset=integer2unsigned(i*op2_bv.size());

    for(std::size_t j=0; j<op2_bv.size(); j++)
      next_bv[offset+j]=
        prop.lselect(eq_lit, op2_bv[j], prev_bv[offset+j]);
  }
}