示例#1
0
void c_typecheck_baset::typecheck_typeof_type(typet &type)
{
  // retain the qualifiers as is
  c_qualifierst c_qualifiers;
  c_qualifiers.read(type);

  if(!((const exprt &)type).has_operands())
  {
    typet t=static_cast<const typet &>(type.find(ID_type_arg));
    typecheck_type(t);
    type.swap(t);
  }
  else
  {
    exprt expr=((const exprt &)type).op0();
    typecheck_expr(expr);

    // undo an implicit address-of
    if(expr.id()==ID_address_of &&
       expr.get_bool(ID_C_implicit))
    {
      assert(expr.operands().size()==1);
      exprt tmp;
      tmp.swap(expr.op0());
      expr.swap(tmp);
    }

    type.swap(expr.type());
  }
  
  c_qualifiers.write(type);
}
示例#2
0
void c_typecheck_baset::typecheck_c_bit_field_type(typet &type)
{
  typecheck_type(type.subtype());

  exprt &width_expr=static_cast<exprt &>(type.add(ID_size));

  typecheck_expr(width_expr);
  make_constant_index(width_expr);

  mp_integer i;
  if(to_integer(width_expr, i))
  {
    err_location(type);
    throw "failed to convert bit field width";
  }

  if(i<0)
  {
    err_location(type);
    throw "bit field width is negative";
  }

  const typet &base_type=follow(type.subtype());
  
  if(base_type.id()==ID_bool)
  {
    if(i>1)
    {
      err_location(type);
      throw "bit field width too large";
    }

    // We don't use bool, as it's really a byte long.
    type.id(ID_unsignedbv);
    type.set(ID_width, integer2long(i));
  }
  else if(base_type.id()==ID_signedbv ||
          base_type.id()==ID_unsignedbv ||
          base_type.id()==ID_c_enum)
  {
    unsigned width=base_type.get_int(ID_width);

    if(i>width)
    {
      err_location(type);
      throw "bit field width too large";
    }

    typet tmp(base_type);
    type.swap(tmp);
    type.set(ID_width, integer2string(i));
  }
  else
  {
    err_location(type);
    str << "bit field with non-integer type: "
        << to_string(base_type);
    throw 0;
  }
}
示例#3
0
void c_typecheck_baset::adjust_function_parameter(typet &type) const
{
  if(type.id()==ID_array)
  {
    type.id(ID_pointer);
    type.remove(ID_size);
    type.remove(ID_C_constant);
  }
  else if(type.id()==ID_code)
  {
    // see ISO/IEC 9899:1999 page 199 clause 8
    pointer_typet tmp;
    tmp.subtype()=type;
    type.swap(tmp);
  }
  else if(type.id()==ID_KnR)
  {
    // any KnR args without type yet?
    type=signed_int_type(); // the default is integer!
  }
}
示例#4
0
void ansi_c_convert_typet::write(typet &type)
{
  type.clear();

  // first, do "other"

  if(!other.empty())
  {
    if(
      double_cnt || float_cnt || signed_cnt || unsigned_cnt || int_cnt ||
      bool_cnt || short_cnt || char_cnt || int8_cnt || int16_cnt || int32_cnt ||
      int64_cnt || ptr32_cnt || ptr64_cnt || long_cnt)
    {
      err_location(location);
      error("illegal type modifier for defined type");
      throw 0;
    }

    if(other.size() != 1)
    {
      err_location(location);
      error("illegal combination of defined types");
      throw 0;
    }

    type.swap(other.front());
  }
  else if(double_cnt || float_cnt)
  {
    if(
      signed_cnt || unsigned_cnt || int_cnt || bool_cnt || int8_cnt ||
      int16_cnt || int32_cnt || int64_cnt || ptr32_cnt || ptr64_cnt ||
      short_cnt || char_cnt)
    {
      err_location(location);
      error("cannot conbine integer type with float");
      throw 0;
    }

    if(double_cnt && float_cnt)
    {
      err_location(location);
      error("conflicting type modifiers");
      throw 0;
    }

    if(long_cnt == 0)
    {
      if(double_cnt != 0)
        type = double_type();
      else
        type = float_type();
    }
    else if(long_cnt == 1 || long_cnt == 2)
    {
      if(double_cnt != 0)
        type = long_double_type();
      else
      {
        err_location(location);
        error("conflicting type modifiers");
        throw 0;
      }
    }
    else
    {
      err_location(location);
      error("illegal type modifier for float");
      throw 0;
    }
  }
  else if(bool_cnt)
  {
    if(
      signed_cnt || unsigned_cnt || int_cnt || short_cnt || int8_cnt ||
      int16_cnt || int32_cnt || int64_cnt || ptr32_cnt || ptr64_cnt ||
      char_cnt || long_cnt)
    {
      err_location(location);
      error("illegal type modifier for boolean type");
      throw 0;
    }

    type.id("bool");
  }
  else if(ptr32_cnt || ptr64_cnt)
  {
    type.id("pointer");
    type.subtype() = typet("empty");
  }
  else
  {
    // it is integer -- signed or unsigned?

    if(signed_cnt && unsigned_cnt)
    {
      err_location(location);
      error("conflicting type modifiers");
      throw 0;
    }
    if(unsigned_cnt)
      type.id("unsignedbv");
    else if(signed_cnt)
      type.id("signedbv");
    else
    {
      if(char_cnt)
        type.id(config.ansi_c.char_is_unsigned ? "unsignedbv" : "signedbv");
      else
        type.id("signedbv");
    }

    // get width

    unsigned width;

    if(int8_cnt || int16_cnt || int32_cnt || int64_cnt)
    {
      if(long_cnt || char_cnt || short_cnt)
      {
        err_location(location);
        error("conflicting type modifiers");
        throw 0;
      }

      if(int8_cnt)
        width = 1 * 8;
      else if(int16_cnt)
        width = 2 * 8;
      else if(int32_cnt)
        width = 4 * 8;
      else if(int64_cnt)
        width = 8 * 8;
      else
        abort();
    }
    else if(short_cnt)
    {
      if(long_cnt || char_cnt)
      {
        err_location(location);
        error("conflicting type modifiers");
        throw 0;
      }

      width = config.ansi_c.short_int_width;
    }
    else if(char_cnt)
    {
      if(long_cnt)
      {
        err_location(location);
        error("illegal type modifier for char type");
        throw 0;
      }

      width = config.ansi_c.char_width;
    }
    else if(long_cnt == 0)
    {
      width = config.ansi_c.int_width;
    }
    else if(long_cnt == 1)
    {
      width = config.ansi_c.long_int_width;
    }
    else if(long_cnt == 2)
    {
      width = config.ansi_c.long_long_int_width;
    }
    else
    {
      err_location(location);
      error("illegal type modifier for integer type");
      throw 0;
    }

    type.width(width);
  }

  c_qualifiers.write(type);
}
void ansi_c_convert_typet::write(typet &type)
{
  type.clear();
  
  // first, do "other"

  if(!other.empty())
  {
    if(double_cnt || float_cnt || signed_cnt ||
       unsigned_cnt || int_cnt || c_bool_cnt || proper_bool_cnt ||
       short_cnt || char_cnt || complex_cnt || long_cnt ||
       int8_cnt || int16_cnt || int32_cnt || int64_cnt ||
       gcc_float128_cnt || gcc_int128_cnt || bv_cnt)
    {
      err_location(location);
      error("illegal type modifier for defined type");
      throw 0;
    }

    if(other.size()!=1)
    {
      err_location(location);
      error("illegal combination of defined types");
      throw 0;
    }

    type.swap(other.front());
  }
  else if(gcc_float128_cnt)
  {
    if(signed_cnt || unsigned_cnt || int_cnt || c_bool_cnt || proper_bool_cnt ||
       int8_cnt || int16_cnt || int32_cnt || int64_cnt ||
       gcc_int128_cnt || bv_cnt ||
       short_cnt || char_cnt)
    {
      err_location(location);
      error("cannot combine integer type with float");
      throw 0;
    }

    if(long_cnt || double_cnt || float_cnt)
    {
      err_location(location);
      error("conflicting type modifiers");
      throw 0;
    }
    
    type=long_double_type();
  }
  else if(double_cnt || float_cnt)
  {
    if(signed_cnt || unsigned_cnt || int_cnt || c_bool_cnt || proper_bool_cnt ||
       int8_cnt || int16_cnt || int32_cnt || int64_cnt ||
       gcc_int128_cnt|| bv_cnt ||
       short_cnt || char_cnt)
    {
      err_location(location);
      error("cannot combine integer type with float");
      throw 0;
    }

    if(double_cnt && float_cnt)
    {
      err_location(location);
      error("conflicting type modifiers");
      throw 0;
    }

    if(long_cnt==0)
    {
      if(double_cnt!=0)
        type=double_type();
      else
        type=float_type();
    }
    else if(long_cnt==1 || long_cnt==2)
    {
      if(double_cnt!=0)
        type=long_double_type();
      else
      {
        err_location(location);
        error("conflicting type modifiers");
        throw 0;
      }
    }
    else
    {
      err_location(location);
      error("illegal type modifier for float");
      throw 0;
    }
  }
  else if(c_bool_cnt)
  {
    if(signed_cnt || unsigned_cnt || int_cnt || short_cnt ||
       int8_cnt || int16_cnt || int32_cnt || int64_cnt ||
       gcc_float128_cnt || bv_cnt || proper_bool_cnt ||
       char_cnt || long_cnt)
    {
      err_location(location);
      error("illegal type modifier for C boolean type");
      throw 0;
    }

    type.id(ID_unsignedbv);
    type.set(ID_width, config.ansi_c.bool_width);
    type.set(ID_C_c_type, ID_bool);
  }
  else if(proper_bool_cnt)
  {
    if(signed_cnt || unsigned_cnt || int_cnt || short_cnt ||
       int8_cnt || int16_cnt || int32_cnt || int64_cnt ||
       gcc_float128_cnt || bv_cnt ||
       char_cnt || long_cnt)
    {
      err_location(location);
      error("illegal type modifier for proper boolean type");
      throw 0;
    }

    type.id(ID_bool);
  }
  else if(complex_cnt && !char_cnt && !signed_cnt && !unsigned_cnt && !short_cnt && !gcc_int128_cnt)
  {
    // the "default" for complex is double
    type=double_type();
  }
  else
  {
    // it is integer -- signed or unsigned?

    if(signed_cnt && unsigned_cnt)
    {
      err_location(location);
      error("conflicting type modifiers");
      throw 0;
    }
    else if(unsigned_cnt)
      type.id(ID_unsignedbv);
    else if(signed_cnt)
      type.id(ID_signedbv);
    else
    {
      if(char_cnt)
        type.id(config.ansi_c.char_is_unsigned?ID_unsignedbv:ID_signedbv);
      else
        type.id(ID_signedbv);
    }

    // get width

    unsigned width;
    
    if(gcc_mode_QI || gcc_mode_HI || gcc_mode_SI || gcc_mode_DI)
    {
      if(gcc_mode_QI)
        width=1*8;
      else if(gcc_mode_HI)
        width=2*8;
      else if(gcc_mode_SI)
        width=4*8;
      else if(gcc_mode_DI)
        width=8*8;
      else
        assert(false);
    }
    else if(int8_cnt || int16_cnt || int32_cnt || int64_cnt || gcc_int128_cnt || bv_cnt)
    {
      if(long_cnt || char_cnt || short_cnt)
      {
        err_location(location);
        error("conflicting type modifiers");
        throw 0;
      }
      
      if(int8_cnt)
        width=1*8;
      else if(int16_cnt)
        width=2*8;
      else if(int32_cnt)
        width=4*8;
      else if(int64_cnt)
        width=8*8;
      else if(bv_cnt)
        width=bv_width;
      else if(gcc_int128_cnt)
        width=128;
      else
        assert(false);
    }
    else if(short_cnt)
    {
      if(long_cnt || char_cnt)
      {
        err_location(location);
        error("conflicting type modifiers");
        throw 0;
      }

      width=config.ansi_c.short_int_width;
    }
    else if(char_cnt)
    {
      if(long_cnt)
      {
        err_location(location);
        error("illegal type modifier for char type");
        throw 0;
      }

      width=config.ansi_c.char_width;
    }
    else if(long_cnt==0)
    {
      width=config.ansi_c.int_width;
    }
    else if(long_cnt==1)
    {
      width=config.ansi_c.long_int_width;
    }
    else if(long_cnt==2)
    {
      width=config.ansi_c.long_long_int_width;
    }
    else
    {
      err_location(location);
      error("illegal type modifier for integer type");
      throw 0;
    }

    type.set(ID_width, width);
  }

  if(vector_size.is_not_nil())
  {
    vector_typet new_type;
    new_type.size()=vector_size;
    new_type.location()=vector_size.location();
    new_type.subtype().swap(type);
    type=new_type;
  }
  
  if(complex_cnt)
  {
    // These take more or less arbitrary subtypes.
    complex_typet new_type;
    new_type.location()=location;
    new_type.subtype()=type;
    type.swap(new_type);
  }

  c_qualifiers.write(type);

  if(packed)
    type.set(ID_C_packed, true);

  if(aligned)
    type.set(ID_C_alignment, alignment);
}
示例#6
0
void c_typecheck_baset::typecheck_type(typet &type)
{
  // we first convert, and then check
  {
    ansi_c_convert_typet ansi_c_convert_type(get_message_handler());

    ansi_c_convert_type.read(type);
    ansi_c_convert_type.write(type);
  }

  if(type.id()==ID_already_typechecked)
  {
    // need to preserve any qualifiers
    c_qualifierst c_qualifiers(type);
    c_qualifiers+=c_qualifierst(type.subtype());
    bool packed=type.get_bool(ID_C_packed);
    exprt alignment=static_cast<const exprt &>(type.find(ID_C_alignment));

    type.swap(type.subtype());

    c_qualifiers.write(type);
    if(packed)
      type.set(ID_C_packed, true);
    if(alignment.is_not_nil())
      type.add(ID_C_alignment, alignment);

    return; // done
  }

  // do we have alignment?
  if(type.find(ID_C_alignment).is_not_nil())
  {
    exprt &alignment=static_cast<exprt &>(type.add(ID_C_alignment));
    if(alignment.id()!=ID_default)
    {
      typecheck_expr(alignment);
      make_constant(alignment);
    }
  }

  if(type.id()==ID_code)
    typecheck_code_type(to_code_type(type));
  else if(type.id()==ID_array)
    typecheck_array_type(to_array_type(type));
  else if(type.id()==ID_pointer)
    typecheck_type(type.subtype());
  else if(type.id()==ID_struct ||
          type.id()==ID_union)
    typecheck_compound_type(to_struct_union_type(type));
  else if(type.id()==ID_c_enum)
    typecheck_c_enum_type(type);
  else if(type.id()==ID_c_enum_tag)
    typecheck_c_enum_tag_type(to_c_enum_tag_type(type));
  else if(type.id()==ID_c_bit_field)
    typecheck_c_bit_field_type(to_c_bit_field_type(type));
  else if(type.id()==ID_typeof)
    typecheck_typeof_type(type);
  else if(type.id()==ID_symbol)
    typecheck_symbol_type(type);
  else if(type.id()==ID_vector)
    typecheck_vector_type(to_vector_type(type));
  else if(type.id()==ID_custom_unsignedbv ||
          type.id()==ID_custom_signedbv ||
          type.id()==ID_custom_floatbv ||
          type.id()==ID_custom_fixedbv)
    typecheck_custom_type(type);
  else if(type.id()==ID_gcc_attribute_mode)
  {
    // get that mode
    irep_idt mode=type.get(ID_size);

    // A list of all modes ist at
    // http://www.delorie.com/gnu/docs/gcc/gccint_53.html
    typecheck_type(type.subtype());

    typet underlying_type=type.subtype();

    // gcc allows this, but clang doesn't; it's a compiler hint only,
    // but we'll try to interpret it the GCC way
    if(underlying_type.id()==ID_c_enum_tag)
    {
      underlying_type=
        follow_tag(to_c_enum_tag_type(underlying_type)).subtype();

      assert(underlying_type.id()==ID_signedbv ||
             underlying_type.id()==ID_unsignedbv);
    }

    if(underlying_type.id()==ID_signedbv ||
       underlying_type.id()==ID_unsignedbv)
    {
      bool is_signed=underlying_type.id()==ID_signedbv;

      typet result;

      if(mode=="__QI__") // 8 bits
        result=is_signed?signed_char_type():unsigned_char_type();
      else if(mode=="__byte__") // 8 bits
        result=is_signed?signed_char_type():unsigned_char_type();
      else if(mode=="__HI__") // 16 bits
        result=is_signed?signed_short_int_type():unsigned_short_int_type();
      else if(mode=="__SI__") // 32 bits
        result=is_signed?signed_int_type():unsigned_int_type();
      else if(mode=="__word__") // long int, we think
        result=is_signed?signed_long_int_type():unsigned_long_int_type();
      else if(mode=="__pointer__") // we think this is size_t/ssize_t
        result=is_signed?signed_size_type():size_type();
      else if(mode=="__DI__") // 64 bits
      {
        if(config.ansi_c.long_int_width==64)
          result=is_signed?signed_long_int_type():unsigned_long_int_type();
        else
        {
          assert(config.ansi_c.long_long_int_width==64);
          result=
            is_signed?signed_long_long_int_type():unsigned_long_long_int_type();
        }
      }
      else if(mode=="__TI__") // 128 bits
        result=is_signed?gcc_signed_int128_type():gcc_unsigned_int128_type();
      else if(mode=="__V2SI__") // vector of 2 ints, deprecated by gcc
        result=
          vector_typet(
            is_signed?signed_int_type():unsigned_int_type(),
            from_integer(2, size_type()));
      else if(mode=="__V4SI__") // vector of 4 ints, deprecated by gcc
        result=
          vector_typet(
            is_signed?signed_int_type():unsigned_int_type(),
            from_integer(4, size_type()));
      else // give up, just use subtype
        result=type.subtype();

      // save the location
      result.add_source_location()=type.source_location();

      if(type.subtype().id()==ID_c_enum_tag)
      {
        const irep_idt &tag_name=
          to_c_enum_tag_type(type.subtype()).get_identifier();

        symbol_tablet::symbolst::iterator entry=
          symbol_table.symbols.find(tag_name);
        assert(entry!=symbol_table.symbols.end());

        entry->second.type.subtype()=result;
      }

      type=result;
    }
    else if(underlying_type.id()==ID_floatbv)
    {
      typet result;

      if(mode=="__SF__") // 32 bits
        result=float_type();
      else if(mode=="__DF__") // 64 bits
        result=double_type();
      else if(mode=="__TF__") // 128 bits
        result=gcc_float128_type();
      else if(mode=="__V2SF__") // vector of 2 floats, deprecated by gcc
        result=vector_typet(float_type(), from_integer(2, size_type()));
      else if(mode=="__V2DF__") // vector of 2 doubles, deprecated by gcc
        result=vector_typet(double_type(), from_integer(2, size_type()));
      else if(mode=="__V4SF__") // vector of 4 floats, deprecated by gcc
        result=vector_typet(float_type(), from_integer(4, size_type()));
      else if(mode=="__V4DF__") // vector of 4 doubles, deprecated by gcc
        result=vector_typet(double_type(), from_integer(4, size_type()));
      else // give up, just use subtype
        result=type.subtype();

      // save the location
      result.add_source_location()=type.source_location();

      type=result;
    }
    else if(underlying_type.id()==ID_complex)
    {
      // gcc allows this, but clang doesn't -- see enums above
      typet result;

      if(mode=="__SC__") // 32 bits
        result=float_type();
      else if(mode=="__DC__") // 64 bits
        result=double_type();
      else if(mode=="__TC__") // 128 bits
        result=gcc_float128_type();
      else // give up, just use subtype
        result=type.subtype();

      // save the location
      result.add_source_location()=type.source_location();

      type=complex_typet(result);
    }
    else
    {
      error().source_location=type.source_location();
      error() << "attribute mode `" << mode
              << "' applied to inappropriate type `"
              << to_string(type) << "'" << eom;
      throw 0;
    }
  }

  // do a mild bit of rule checking

  if(type.get_bool(ID_C_restricted) &&
     type.id()!=ID_pointer &&
     type.id()!=ID_array)
  {
    error().source_location=type.source_location();
    error() << "only a pointer can be 'restrict'" << eom;
    throw 0;
  }
}