示例#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;
  }
}
示例#2
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;
    }
  }
}