Esempio n. 1
0
void c_typecheck_baset::typecheck_array_type(array_typet &type)
{
  exprt &size=type.size();
  locationt location=size.find_location();

  // check subtype
  typecheck_type(type.subtype());
  
  // we don't allow void as subtype
  if(follow(type.subtype()).id()==ID_empty)
  {
    err_location(type);
    str << "array of voids";
    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;
    simplify(tmp_size, *this);

    if(tmp_size.is_constant())
    {
      mp_integer s;
      if(to_integer(tmp_size, s))
      {
        err_location(location);
        str << "failed to convert constant: "
            << tmp_size.pretty();
        throw 0;
      }

      if(s<0)
      {
        err_location(location);
        str << "array size must not be negative, "
               "but got " << s;
        throw 0;
      }
      
      size=tmp_size;
    }
    else if(tmp_size.id()==ID_infinity)
      size=tmp_size;
  }
}
Esempio n. 2
0
exprt boolbvt::bv_get_unbounded_array(
  const irep_idt &identifier,
  const array_typet &type) const
{
  // first, try to get size
  
  const exprt &size_expr=type.size();
  exprt size=get(size_expr);
  
  // no size, give up
  if(size.is_nil()) return nil_exprt();

  // get the numeric value, unless it's infinity
  mp_integer size_mpint;

  if(size.id()!=ID_infinity)
  {
    if(to_integer(size, size_mpint))
      return nil_exprt();

    // simple sanity check
    if(size_mpint<0)
      return nil_exprt();
  }
  else
    size_mpint=0;

  // search array indices

  typedef std::map<mp_integer, exprt> valuest;
  valuest values;

  {
    unsigned number;

    symbol_exprt array_expr;
    array_expr.type()=type;
    array_expr.set_identifier(identifier);

    if(arrays.get_number(array_expr, number))
      return nil_exprt();

    // get root
    number=arrays.find_number(number);
    
    assert(number<index_map.size());
    const index_sett &index_set=index_map[number];
    
    for(index_sett::const_iterator it1=
        index_set.begin();
        it1!=index_set.end();
        it1++)
    {
      index_exprt index;
      index.type()=type.subtype();
      index.array()=array_expr;
      index.index()=*it1;
      
      exprt value=bv_get_cache(index);
      exprt index_value=bv_get_cache(*it1);
      
      if(!index_value.is_nil())
      {
        mp_integer index_mpint;

        if(!to_integer(index_value, index_mpint))
        {
          if(value.is_nil())
            values[index_mpint]=exprt(ID_unknown, type.subtype());
          else
            values[index_mpint]=value;
        }
      }
    }
  }

  exprt result;

  if(size_mpint>100 || size.id()==ID_infinity)
  {
    result=exprt("array-list", type);
    result.type().set(ID_size, integer2string(size_mpint));

    result.operands().reserve(values.size()*2);

    for(valuest::const_iterator it=values.begin();
        it!=values.end();
        it++)
    {
      exprt index=from_integer(it->first, size.type());
      result.copy_to_operands(index, it->second);
    }
  }
  else
  {
    // set the size
    result=exprt(ID_array, type);
    result.type().set(ID_size, size);

    unsigned long size_int=integer2long(size_mpint);

    // allocate operands
    result.operands().resize(size_int);

    for(unsigned i=0; i<size_int; i++)
      result.operands()[i]=exprt(ID_unknown);

    // search uninterpreted functions

    for(valuest::iterator it=values.begin();
        it!=values.end();
        it++)
      if(it->first>=0 && it->first<size_mpint)
        result.operands()[integer2long(it->first)].swap(it->second);
  }
  
  return result;
}
Esempio n. 3
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;
    }
  }
}
Esempio n. 4
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]);
  }
}