Beispiel #1
0
 bool is_string_type(const typet &t) const
 {
   return
     (t.id()==ID_pointer || t.id()==ID_array) &&
     (t.subtype().id()==ID_signedbv || t.subtype().id()==ID_unsignedbv) &&
     (to_bitvector_type(t.subtype()).get_width()==config.ansi_c.char_width);
 }
Beispiel #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;
  }
}
Beispiel #3
0
bool c_typecheck_baset::is_complete_type(const typet &type) const
{
  if(type.id()==ID_incomplete_struct ||
     type.id()==ID_incomplete_union)
    return false;
  else if(type.id()==ID_array)
  {
    if(to_array_type(type).size().is_nil()) return false;
    return is_complete_type(type.subtype());
  }
  else if(type.id()==ID_struct || type.id()==ID_union)
  {
    const struct_union_typet::componentst &components=
      to_struct_union_type(type).components();
    for(struct_union_typet::componentst::const_iterator
        it=components.begin();
        it!=components.end();
        it++)
      if(!is_complete_type(it->type()))
        return false;
  }
  else if(type.id()==ID_vector)
    return is_complete_type(type.subtype());
  else if(type.id()==ID_symbol)
    return is_complete_type(follow(type));

  return true;
}
Beispiel #4
0
bool is_void_pointer(const typet &type)
{
  if(type.id()==ID_pointer)
  {
    if(type.subtype().id()==ID_empty)
      return true;
  
    return is_void_pointer(type.subtype());
  }
  else
    return false;
}
Beispiel #5
0
exprt gen_one(const typet &type)
{
  const irep_idt type_id=type.id();
  exprt result=constant_exprt(type);

  if(type_id==ID_bool ||
     type_id==ID_rational ||
     type_id==ID_real ||
     type_id==ID_integer ||
     type_id==ID_natural)
  {
    result.set(ID_value, ID_1);
  }
  else if(type_id==ID_unsignedbv ||
          type_id==ID_signedbv ||
          type_id==ID_c_enum)
  {
    std::string value;
    unsigned width=to_bitvector_type(type).get_width();
    for(unsigned i=0; i<width-1; i++)
      value+='0';
    value+='1';
    result.set(ID_value, value);
  }
  else if(type_id==ID_fixedbv)
  {
    fixedbvt fixedbv;
    fixedbv.spec=to_fixedbv_type(type);
    fixedbv.from_integer(1);
    result=fixedbv.to_expr();
  }
  else if(type_id==ID_floatbv)
  {
    ieee_floatt ieee_float;
    ieee_float.spec=to_floatbv_type(type);
    ieee_float.from_integer(1);
    result=ieee_float.to_expr();
  }
  else if(type_id==ID_complex)
  {
    result=exprt(ID_complex, type);
    result.operands().resize(2);
    result.op0()=gen_one(type.subtype());
    result.op1()=gen_zero(type.subtype());
  }
  else
    result.make_nil();

  return result;
}
Beispiel #6
0
void java_bytecode_parsert::get_class_refs_rec(const typet &src)
{
  if(src.id()==ID_code)
  {
    const code_typet &ct=to_code_type(src);
    const typet &rt=ct.return_type();
    get_class_refs_rec(rt);
    for(const auto &p : ct.parameters())
      get_class_refs_rec(p.type());
  }
  else if(src.id()==ID_symbol)
  {
    irep_idt name=src.get(ID_C_base_name);
    if(has_prefix(id2string(name), "array["))
    {
      const typet &element_type=
        static_cast<const typet &>(src.find(ID_C_element_type));
      get_class_refs_rec(element_type);
    }
    else
      parse_tree.class_refs.insert(name);
  }
  else if(src.id()==ID_struct)
  {
    const struct_typet &struct_type=to_struct_type(src);
    for(const auto &c : struct_type.components())
      get_class_refs_rec(c.type());
  }
  else if(src.id()==ID_pointer)
    get_class_refs_rec(src.subtype());
}
void cpp_typecheckt::check_template_restrictions(
  const irept &cpp_name,
  const irep_idt &final_identifier,
  const typet &final_type)
{
  if(final_type.id()==ID_template)
  {
    // subtype must be class or function

    if(final_type.subtype().id()!=ID_struct &&
       final_type.subtype().id()!=ID_code)
    {
      err_location(cpp_name);
      str << "template only allowed with classes or functions,"
             " but got `" << to_string(final_type.subtype()) << "'";
      throw 0;
    }
  }
}
Beispiel #8
0
void c_typecheck_baset::typecheck_type(typet &type)
{
  // we first convert, and then check
  
  // 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)
  {
  }
  else if(type.id()==ID_c_bitfield)
    typecheck_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);

  // do a bit of rule checking

  if(type.get_bool(ID_C_restricted) &&
     type.id()!=ID_pointer &&
     type.id()!=ID_array)
  {
    err_location(type);
    error("only a pointer can be 'restrict'");
    throw 0;
  }
  
}
void java_bytecode_typecheckt::typecheck_type(typet &type)
{
  if(type.id()==ID_symbol)
  {
    irep_idt identifier=to_symbol_type(type).get_identifier();

    symbol_tablet::symbolst::const_iterator s_it=
      symbol_table.symbols.find(identifier);

    // must exist already in the symbol table
    if(s_it==symbol_table.symbols.end())
    {
      error() << "failed to find type symbol "<< identifier << eom;
      throw 0;
    }

    assert(s_it->second.is_type);
  }
  else if(type.id()==ID_pointer)
  {
    typecheck_type(type.subtype());
  }
  else if(type.id()==ID_array)
  {
    typecheck_type(type.subtype());
    typecheck_expr(to_array_type(type).size());
  }
  else if(type.id()==ID_code)
  {
    code_typet &code_type=to_code_type(type);
    typecheck_type(code_type.return_type());

    code_typet::parameterst &parameters=code_type.parameters();

    for(code_typet::parameterst::iterator
        it=parameters.begin(); it!=parameters.end(); it++)
      typecheck_type(it->type());
  }
}
bool remove_const_function_pointerst::is_const_type(const typet &type) const
{
  c_qualifierst qualifers(type);
  if(type.id()==ID_array)
  {
    c_qualifierst array_type_qualifers(type.subtype());
    return qualifers.is_constant || array_type_qualifers.is_constant;
  }
  else
  {
    return qualifers.is_constant;
  }
}
Beispiel #11
0
exprt gen_zero(const typet &type)
{
  exprt result;

  const irep_idt type_id=type.id();

  result=constant_exprt(type);

  if(type_id==ID_rational ||
     type_id==ID_real ||
     type_id==ID_integer ||
     type_id==ID_natural ||
     type_id==ID_complex ||
     type_id==ID_c_enum)
  {
    result.set(ID_value, ID_0);
  }
  else if(type_id==ID_unsignedbv ||
          type_id==ID_signedbv ||
          type_id==ID_verilogbv ||
          type_id==ID_floatbv ||
          type_id==ID_fixedbv)
  {
    std::string value;
    unsigned width=to_bitvector_type(type).get_width();

    for(unsigned i=0; i<width; i++)
      value+='0';

    result.set(ID_value, value);
  }
  else if(type_id==ID_complex)
  {
    result=exprt(ID_complex, type);
    exprt sub_zero=gen_zero(type.subtype());
    result.operands().resize(2, sub_zero);
  }
  else if(type_id==ID_bool)
  {
    result.make_false();
  }
  else if(type_id==ID_pointer)
  {
    result.set(ID_value, ID_NULL);
  }
  else
    result.make_nil();

  return result;
}
Beispiel #12
0
bool restrict_bv_size(typet &type, const size_t width_in_bits)
{
  const irep_idt &type_id=type.id();
  if (ID_code == type_id)
    return restrict_bv_size(to_code_type(type), width_in_bits);
  if (ID_struct == type_id || ID_union == type_id)
    return restrict_bv_size(to_struct_union_type(type), width_in_bits);
  if (static_cast<const typet &>(type).subtype().is_not_nil())
    restrict_bv_size(type.subtype(), width_in_bits);
  if (!is_bv_type(type)) return false;
  bitvector_typet &bvtype=to_bitvector_type(type);
  if (width_in_bits >= bvtype.get_width()) return false;
  to_bitvector_type(type).set_width(width_in_bits);
  return true;
}
Beispiel #13
0
bool replace_symbolt::replace(typet &dest)
{
  if(dest.has_subtype())
    replace(dest.subtype());

  Forall_subtypes(it, dest)
    replace(*it);
    
  if(dest.id()=="struct" ||
     dest.id()=="union")
  {
    struct_typet &struct_type = to_struct_type(dest);    
    struct_typet::componentst &components = struct_type.components();
    for (struct_typet::componentst::iterator it = components.begin();
         it!=components.end();
         it++)
      replace(*it);
  } 
  else if(dest.is_code())
  {
    code_typet &code_type=to_code_type(dest);
    code_typet::argumentst &arguments=code_type.arguments();
    for (code_typet::argumentst::iterator it = arguments.begin();
         it!=arguments.end();
         it++)
      replace(*it);
  }
  
  if(dest.id()=="symbol")
  {
    type_mapt::const_iterator it=
      type_map.find(dest.identifier());

    if(it!=type_map.end())
    {
      dest=it->second;
      return false;
    }
  }

  return true;
}
Beispiel #14
0
unsigned alignment(const typet &type, const namespacet &ns)
{
  if(type.id()==ID_array ||
     type.id()==ID_incomplete_array)
    return alignment(type.subtype(), ns);
  else if(type.id()==ID_struct || type.id()==ID_union)
  {
    const struct_union_typet::componentst &components=
      to_struct_union_type(type).components();

    unsigned result=1;

    // get the max
    // (should really be the smallest common denominator)
    for(struct_union_typet::componentst::const_iterator
        it=components.begin();
        it!=components.end();
        it++)
      result=std::max(result, alignment(it->type(), ns));

    return result;
  }
  else if(type.id()==ID_unsignedbv ||
          type.id()==ID_signedbv ||
          type.id()==ID_fixedbv ||
          type.id()==ID_floatbv)
  {
    unsigned width=type.get_int(ID_width);
    return width%8?width/8+1:width/8;
  }
  else if(type.id()==ID_pointer)
  {
    unsigned width=config.ansi_c.pointer_width;
    return width%8?width/8+1:width/8;
  }
  else if(type.id()==ID_symbol)
    return alignment(ns.follow(type), ns);

  return 1;
}
Beispiel #15
0
exprt c_sizeoft::sizeof_rec(const typet &type)
{
  exprt dest;

  if(type.id()==ID_signedbv ||
     type.id()==ID_unsignedbv ||
     type.id()==ID_floatbv ||
     type.id()==ID_fixedbv ||
     type.id()==ID_c_enum ||
     type.id()==ID_incomplete_c_enum)
  {
    // We round up to bytes.
    // See special treatment for bit-fields below.
    unsigned bits=type.get_int(ID_width);
    unsigned bytes=bits/8;
    if((bits%8)!=0) bytes++;
    dest=from_integer(bytes, size_type());
  }
  else if(type.id()==ID_pointer)
  {
    // the following is an MS extension
    if(type.get_bool(ID_C_ptr32))
      return from_integer(4, size_type());
             
    unsigned bits=config.ansi_c.pointer_width;
    unsigned bytes=bits/8;
    if((bits%8)!=0) bytes++;
    dest=from_integer(bytes, size_type());
  }
  else if(type.id()==ID_bool)
  {
    // We fit booleans into a byte.
    dest=from_integer(1, size_type());
  }
  else if(type.id()==ID_array)
  {
    const exprt &size_expr=
      to_array_type(type).size();
      
    if(size_expr.is_nil())
    {
      // treated like an empty array
      dest=from_integer(0, size_type());
    }
    else
    {
      exprt tmp_dest=sizeof_rec(type.subtype());

      if(tmp_dest.is_nil())
        return tmp_dest;

      mp_integer a, b;

      if(!to_integer(tmp_dest, a) &&
         !to_integer(size_expr, b))
      {
        dest=from_integer(a*b, size_type());
      }
      else
      {
        dest.id(ID_mult);
        dest.type()=size_type();
        dest.copy_to_operands(size_expr);
        dest.move_to_operands(tmp_dest);
        c_implicit_typecast(dest.op0(), dest.type(), ns);
        c_implicit_typecast(dest.op1(), dest.type(), ns);
      }
    }
  }
  else if(type.id()==ID_struct)
  {
    const struct_typet::componentst &components=
      to_struct_type(type).components();

    dest=from_integer(0, size_type());
    
    mp_integer bit_field_width=0;

    for(struct_typet::componentst::const_iterator
        it=components.begin();
        it!=components.end();
        it++)
    {
      const typet &sub_type=ns.follow(it->type());

      if(it->get_bool(ID_is_type))
      {
      }
      else if(sub_type.id()==ID_code)
      {
      }
      else if(it->get_is_bit_field())
      {
        // this needs to be a signedbv/unsignedbv/enum
        if(sub_type.id()!=ID_signedbv &&
           sub_type.id()!=ID_unsignedbv &&
           sub_type.id()!=ID_c_enum)
          return nil_exprt();
          
        // We just sum them up.
        // This assumes they are properly padded.
        bit_field_width+=sub_type.get_int(ID_width);
      }
      else
      {
        exprt tmp=sizeof_rec(sub_type);

        if(tmp.is_nil())
          return tmp;

        dest=plus_exprt(dest, tmp);
      }
    }
    
    if(bit_field_width!=0)
      dest=plus_exprt(dest, from_integer(bit_field_width/8, size_type()));
  }
  else if(type.id()==ID_union)
  {
    const irept::subt &components=
      type.find(ID_components).get_sub();

    mp_integer max_size=0;

    forall_irep(it, components)
    {
      if(it->get_bool(ID_is_type))
        continue;

      const typet &sub_type=static_cast<const typet &>(it->find(ID_type));

      if(sub_type.id()==ID_code)
      {
      }
      else
      {
        exprt tmp=sizeof_rec(sub_type);

        if(tmp.is_nil())
          return tmp;
          
        simplify(tmp, ns);

        mp_integer tmp_int;

        if(to_integer(tmp, tmp_int))
          return static_cast<const exprt &>(get_nil_irep());

        if(tmp_int>max_size) max_size=tmp_int;
      }
    }

    dest=from_integer(max_size, size_type());
  }
  else if(type.id()==ID_symbol)
void cpp_declarator_convertert::combine_types(
    const source_locationt &source_location,
    const typet &decl_type,
    symbolt &symbol)
{
    if(symbol.type.id()==decl_type.id() &&
            decl_type.id()==ID_code)
    {
        // functions need special treatment due
        // to argument names, default values, and inlined-ness
        const code_typet &decl_code_type=to_code_type(decl_type);
        code_typet &symbol_code_type=to_code_type(symbol.type);

        if(decl_code_type.get_inlined())
            symbol_code_type.set_inlined(true);

        if(decl_code_type.return_type()==symbol_code_type.return_type() &&
                decl_code_type.parameters().size()==symbol_code_type.parameters().size())
        {
            for(unsigned i=0; i<decl_code_type.parameters().size(); i++)
            {
                const code_typet::parametert &decl_parameter=decl_code_type.parameters()[i];
                code_typet::parametert &symbol_parameter=symbol_code_type.parameters()[i];

                // first check type
                if(decl_parameter.type()!=symbol_parameter.type())
                {
                    // The 'this' parameter of virtual functions mismatches
                    if(i!=0 || !symbol_code_type.get_bool("#is_virtual"))
                    {
                        cpp_typecheck.err_location(source_location);
                        cpp_typecheck.str << "symbol `" << symbol.display_name()
                                          << "': parameter " << (i+1) << " type mismatch"
                                          << std::endl;
                        cpp_typecheck.str << "previous type: "
                                          << cpp_typecheck.to_string(symbol_parameter.type()) << std::endl;
                        cpp_typecheck.str << "new type: "
                                          << cpp_typecheck.to_string(decl_parameter.type());
                        throw 0;
                    }
                }

                if(symbol.value.is_nil())
                {
                    symbol_parameter.set_base_name(decl_parameter.get_base_name());
                    symbol_parameter.set_identifier(decl_parameter.get_identifier());
                    symbol_parameter.add_source_location()=decl_parameter.source_location();
                }
            }

            // ok
            return;
        }
    }
    else if(symbol.type==decl_type)
        return; // ok
    else if(symbol.type.id()==ID_array &&
            symbol.type.find(ID_size).is_nil() &&
            decl_type.id()==ID_array &&
            symbol.type.subtype()==decl_type.subtype())
    {
        symbol.type = decl_type;
        return; // ok
    }

    cpp_typecheck.err_location(source_location);
    cpp_typecheck.str << "symbol `" << symbol.display_name()
                      << "' already declared with different type:"
                      << std::endl;
    cpp_typecheck.str << "original: "
                      << cpp_typecheck.to_string(symbol.type) << std::endl;
    cpp_typecheck.str << "     new: "
                      << cpp_typecheck.to_string(final_type);
    throw 0;
}
Beispiel #17
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);
}
Beispiel #18
0
bool string_abstractiont::is_ptr_string_struct(const typet &type) const
{
  return type.id()==ID_pointer &&
    type_eq(type.subtype(), string_struct, ns);
}
Beispiel #19
0
void ansi_c_convert_typet::read_rec(const typet &type)
{
  if(type.id()==ID_merged_type)
  {
    forall_subtypes(it, type)
      read_rec(*it);
  }
  else if(type.id()==ID_signed)
    signed_cnt++;
  else if(type.id()==ID_unsigned)
    unsigned_cnt++;
  else if(type.id()==ID_ptr32)
    c_qualifiers.is_ptr32=true;
  else if(type.id()==ID_ptr64)
    c_qualifiers.is_ptr64=true;
  else if(type.id()==ID_volatile)
    c_qualifiers.is_volatile=true;
  else if(type.id()==ID_asm)
  {
    // These are called 'asm labels' by GCC.
    // ignore for now
  }
  else if(type.id()==ID_const)
    c_qualifiers.is_constant=true;
  else if(type.id()==ID_restrict)
    c_qualifiers.is_restricted=true;
  else if(type.id()==ID_atomic)
    c_qualifiers.is_atomic=true;
  else if(type.id()==ID_atomic_type_specifier)
  {
    // this gets turned into the qualifier, uh
    c_qualifiers.is_atomic=true;
    read_rec(type.subtype());
  }
  else if(type.id()==ID_char)
    char_cnt++;
  else if(type.id()==ID_int)
    int_cnt++;
  else if(type.id()==ID_int8)
    int8_cnt++;
  else if(type.id()==ID_int16)
    int16_cnt++;
  else if(type.id()==ID_int32)
    int32_cnt++;
  else if(type.id()==ID_int64)
    int64_cnt++;
  else if(type.id()==ID_gcc_float128)
    gcc_float128_cnt++;
  else if(type.id()==ID_gcc_int128)
    gcc_int128_cnt++;
  else if(type.id()==ID_gcc_attribute_mode)
  {
    gcc_attribute_mode=type;
  }
  else if(type.id()==ID_gcc_attribute)
  {
  }
  else if(type.id()==ID_msc_based)
  {
    const exprt &as_expr=static_cast<const exprt &>(static_cast<const irept &>(type));
    assert(as_expr.operands().size()==1);
    msc_based=as_expr.op0();
  }
  else if(type.id()==ID_custom_bv)
  {
    bv_cnt++;
    const exprt &size_expr=
      static_cast<const exprt &>(type.find(ID_size));
      
    bv_width=size_expr;
  }
  else if(type.id()==ID_custom_floatbv)
  {
    floatbv_cnt++;

    const exprt &size_expr=
      static_cast<const exprt &>(type.find(ID_size));
    const exprt &fsize_expr=
      static_cast<const exprt &>(type.find(ID_f));

    bv_width=size_expr;
    fraction_width=fsize_expr;
  }
  else if(type.id()==ID_custom_fixedbv)
  {
    fixedbv_cnt++;

    const exprt &size_expr=
      static_cast<const exprt &>(type.find(ID_size));
    const exprt &fsize_expr=
      static_cast<const exprt &>(type.find(ID_f));

    bv_width=size_expr;
    fraction_width=fsize_expr;
  }
  else if(type.id()==ID_short)
    short_cnt++;
  else if(type.id()==ID_long)
    long_cnt++;
  else if(type.id()==ID_double)
    double_cnt++;
  else if(type.id()==ID_float)
    float_cnt++;
  else if(type.id()==ID_c_bool)
    c_bool_cnt++;
  else if(type.id()==ID_proper_bool)
    proper_bool_cnt++;
  else if(type.id()==ID_complex)
    complex_cnt++;
  else if(type.id()==ID_static)
    c_storage_spec.is_static=true;
  else if(type.id()==ID_thread_local)
    c_storage_spec.is_thread_local=true;
  else if(type.id()==ID_inline)
    c_storage_spec.is_inline=true;
  else if(type.id()==ID_extern)
    c_storage_spec.is_extern=true;
  else if(type.id()==ID_typedef)
    c_storage_spec.is_typedef=true;
  else if(type.id()==ID_register)
    c_storage_spec.is_register=true;
  else if(type.id()==ID_auto)
  {
    // ignore
  }
  else if(type.id()==ID_packed)
    packed=true;
  else if(type.id()==ID_aligned)
  {
    aligned=true;

    // may come with size or not
    if(type.find(ID_size).is_nil())
      alignment=exprt(ID_default);
    else
      alignment=static_cast<const exprt &>(type.find(ID_size));
  }
  else if(type.id()==ID_transparent_union)
  {
    c_qualifiers.is_transparent_union=true;
  }
  else if(type.id()==ID_vector)
    vector_size=to_vector_type(type).size();
  else if(type.id()==ID_void)
  {
    // we store 'void' as 'empty'
    typet tmp=type;
    tmp.id(ID_empty);
    other.push_back(tmp);
  }
  else if(type.id()==ID_msc_declspec)
  {
    const exprt &as_expr=
      static_cast<const exprt &>(static_cast<const irept &>(type));
      
    forall_operands(it, as_expr)
    {
      // these are symbols
      const irep_idt &id=it->get(ID_identifier);

      if(id=="thread")
        c_storage_spec.is_thread_local=true;
      else if(id=="align")
      {
        assert(it->operands().size()==1);
        aligned=true;
        alignment=it->op0();
      }
    }
  }
  else
void cpp_typecheckt::typecheck_type(typet &type)
{
  assert(!type.id().empty());
  assert(type.is_not_nil());

  try
  {
    cpp_convert_plain_type(type);
  }

  catch(const char *err)
  {
    error().source_location=type.source_location();
    error() << err << eom;
    throw 0;
  }

  catch(const std::string &err)
  {
    error().source_location=type.source_location();
    error() << err << eom;
    throw 0;
  }

  if(type.id()==ID_cpp_name)
  {
    c_qualifierst qualifiers(type);

    cpp_namet cpp_name;
    cpp_name.swap(type);

    exprt symbol_expr=resolve(
      cpp_name,
      cpp_typecheck_resolvet::wantt::TYPE,
      cpp_typecheck_fargst());

    if(symbol_expr.id()!=ID_type)
    {
      error().source_location=type.source_location();
      error() << "error: expected type" << eom;
      throw 0;
    }

    type=symbol_expr.type();
    assert(type.is_not_nil());

    if(type.get_bool(ID_C_constant))
      qualifiers.is_constant = true;

    qualifiers.write(type);
  }
  else if(type.id()==ID_struct ||
          type.id()==ID_union)
  {
    typecheck_compound_type(to_struct_union_type(type));
  }
  else if(type.id()==ID_pointer)
  {
    // the pointer might have a qualifier, but do subtype first
    typecheck_type(type.subtype());

    // Check if it is a pointer-to-member
    if(type.find("to-member").is_not_nil())
    {
      // these can point either to data members or member functions
      // of a class

      typet &class_object=static_cast<typet &>(type.add("to-member"));

      if(class_object.id()==ID_cpp_name)
      {
        assert(class_object.get_sub().back().id()=="::");
        class_object.get_sub().pop_back();
      }

      typecheck_type(class_object);

      // there may be parameters if this is a pointer to member function
      if(type.subtype().id()==ID_code)
      {
        irept::subt &parameters=type.subtype().add(ID_parameters).get_sub();

        if(parameters.empty() ||
           parameters.front().get(ID_C_base_name)!=ID_this)
        {
          // Add 'this' to the parameters
          exprt a0(ID_parameter);
          a0.set(ID_C_base_name, ID_this);
          a0.type().id(ID_pointer);
          a0.type().subtype() = class_object;
          parameters.insert(parameters.begin(), a0);
        }
      }
    }
  }
  else if(type.id()==ID_array)
  {
    exprt &size_expr=to_array_type(type).size();

    if(size_expr.is_not_nil())
    {
      typecheck_expr(size_expr);
      simplify(size_expr, *this);
    }

    typecheck_type(type.subtype());

    if(type.subtype().get_bool(ID_C_constant))
      type.set(ID_C_constant, true);

    if(type.subtype().get_bool(ID_C_volatile))
      type.set(ID_C_volatile, true);
  }
  else if(type.id()==ID_code)
  {
    code_typet &code_type=to_code_type(type);
    typecheck_type(code_type.return_type());

    code_typet::parameterst &parameters=code_type.parameters();

    for(auto &param : parameters)
    {
      typecheck_type(param.type());

      // see if there is a default value
      if(param.has_default_value())
      {
        typecheck_expr(param.default_value());
        implicit_typecast(param.default_value(), param.type());
      }
    }
  }
  else if(type.id()==ID_template)
  {
    typecheck_type(type.subtype());
  }
  else if(type.id()==ID_c_enum)
  {
    typecheck_enum_type(type);
  }
  else if(type.id()==ID_c_enum_tag)
  {
  }
  else if(type.id()==ID_c_bit_field)
  {
    typecheck_c_bit_field_type(to_c_bit_field_type(type));
  }
  else if(type.id()==ID_unsignedbv ||
          type.id()==ID_signedbv ||
          type.id()==ID_bool ||
          type.id()==ID_floatbv ||
          type.id()==ID_fixedbv ||
          type.id()==ID_empty)
  {
  }
  else if(type.id()==ID_symbol)
  {
  }
  else if(type.id()==ID_constructor ||
          type.id()==ID_destructor)
  {
  }
  else if(type.id()=="cpp-cast-operator")
  {
  }
  else if(type.id()=="cpp-template-type")
  {
  }
  else if(type.id()==ID_typeof)
  {
    exprt e=static_cast<const exprt &>(type.find(ID_expr_arg));

    if(e.is_nil())
    {
      typet tmp_type=
        static_cast<const typet &>(type.find(ID_type_arg));

      if(tmp_type.id()==ID_cpp_name)
      {
        // this may be ambiguous -- it can be either a type or
        // an expression

        cpp_typecheck_fargst fargs;

        exprt symbol_expr=resolve(
          to_cpp_name(static_cast<const irept &>(tmp_type)),
          cpp_typecheck_resolvet::wantt::BOTH,
          fargs);

        type=symbol_expr.type();
      }
      else
      {
        typecheck_type(tmp_type);
        type=tmp_type;
      }
    }
    else
    {
      typecheck_expr(e);
      type=e.type();
    }
  }
  else if(type.id()==ID_decltype)
  {
    exprt e=static_cast<const exprt &>(type.find(ID_expr_arg));
    typecheck_expr(e);
    type=e.type();
  }
  else if(type.id()==ID_unassigned)
  {
    // ignore, for template parameter guessing
  }
  else if(type.id()==ID_template_class_instance)
  {
    // ok (internally generated)
  }
  else if(type.id()==ID_block_pointer)
  {
    // This is an Apple extension for lambda-like constructs.
    // http://thirdcog.eu/pwcblocks/
  }
  else if(type.id()==ID_nullptr)
  {
  }
  else
  {
    error().source_location=type.source_location();
    error() << "unexpected cpp type: " << type.pretty() << eom;
    throw 0;
  }

  assert(type.is_not_nil());
}
Beispiel #21
0
exprt boolbvt::bv_get_rec(
    const bvt &bv,
    const std::vector<bool> &unknown,
    std::size_t offset,
    const typet &type) const
{
    if(type.id()==ID_symbol)
        return bv_get_rec(bv, unknown, offset, ns.follow(type));

    std::size_t width=boolbv_width(type);

    assert(bv.size()==unknown.size());
    assert(bv.size()>=offset+width);

    if(type.id()==ID_bool)
    {
        if(!unknown[offset])
        {
            switch(prop.l_get(bv[offset]).get_value())
            {
            case tvt::tv_enumt::TV_FALSE:
                return false_exprt();
            case tvt::tv_enumt::TV_TRUE:
                return true_exprt();
            default:
                return false_exprt(); // default
            }
        }

        return nil_exprt();
    }

    bvtypet bvtype=get_bvtype(type);

    if(bvtype==IS_UNKNOWN)
    {
        if(type.id()==ID_array)
        {
            const typet &subtype=type.subtype();
            std::size_t sub_width=boolbv_width(subtype);

            if(sub_width!=0)
            {
                exprt::operandst op;
                op.reserve(width/sub_width);

                for(std::size_t new_offset=0;
                        new_offset<width;
                        new_offset+=sub_width)
                {
                    op.push_back(
                        bv_get_rec(bv, unknown, offset+new_offset, subtype));
                }

                exprt dest=exprt(ID_array, type);
                dest.operands().swap(op);
                return dest;
            }
        }
        else if(type.id()==ID_struct_tag)
        {
            return bv_get_rec(bv, unknown, offset, ns.follow_tag(to_struct_tag_type(type)));
        }
        else if(type.id()==ID_union_tag)
        {
            return bv_get_rec(bv, unknown, offset, ns.follow_tag(to_union_tag_type(type)));
        }
        else if(type.id()==ID_struct)
        {
            const struct_typet &struct_type=to_struct_type(type);
            const struct_typet::componentst &components=struct_type.components();
            std::size_t new_offset=0;
            exprt::operandst op;
            op.reserve(components.size());

            for(struct_typet::componentst::const_iterator
                    it=components.begin();
                    it!=components.end();
                    it++)
            {
                const typet &subtype=ns.follow(it->type());
                op.push_back(nil_exprt());

                std::size_t sub_width=boolbv_width(subtype);

                if(sub_width!=0)
                {
                    op.back()=bv_get_rec(bv, unknown, offset+new_offset, subtype);
                    new_offset+=sub_width;
                }
            }

            struct_exprt dest(type);
            dest.operands().swap(op);
            return dest;
        }
        else if(type.id()==ID_union)
        {
            const union_typet &union_type=to_union_type(type);
            const union_typet::componentst &components=union_type.components();

            assert(!components.empty());

            // Any idea that's better than just returning the first component?
            std::size_t component_nr=0;

            union_exprt value(union_type);

            value.set_component_name(
                components[component_nr].get_name());

            const typet &subtype=components[component_nr].type();

            value.op()=bv_get_rec(bv, unknown, offset, subtype);

            return value;
        }
        else if(type.id()==ID_vector)
        {
            const typet &subtype=ns.follow(type.subtype());
            std::size_t sub_width=boolbv_width(subtype);

            if(sub_width!=0 && width%sub_width==0)
            {
                std::size_t size=width/sub_width;
                exprt value(ID_vector, type);
                value.operands().resize(size);

                for(std::size_t i=0; i<size; i++)
                    value.operands()[i]=
                        bv_get_rec(bv, unknown, i*sub_width, subtype);

                return value;
            }
        }
        else if(type.id()==ID_complex)
        {
            const typet &subtype=ns.follow(type.subtype());
            std::size_t sub_width=boolbv_width(subtype);

            if(sub_width!=0 && width==sub_width*2)
            {
                exprt value(ID_complex, type);
                value.operands().resize(2);

                value.op0()=bv_get_rec(bv, unknown, 0*sub_width, subtype);
                value.op1()=bv_get_rec(bv, unknown, 1*sub_width, subtype);

                return value;
            }
        }
    }

    std::string value;

    for(std::size_t bit_nr=offset; bit_nr<offset+width; bit_nr++)
    {
        char ch;
        if(unknown[bit_nr])
            ch='0';
        else
            switch(prop.l_get(bv[bit_nr]).get_value())
            {
            case tvt::tv_enumt::TV_FALSE:
                ch='0';
                break;
            case tvt::tv_enumt::TV_TRUE:
                ch='1';
                break;
            case tvt::tv_enumt::TV_UNKNOWN:
                ch='0';
                break;
            default:
                assert(false);
            }

        value=ch+value;
    }

    switch(bvtype)
    {
    case IS_UNKNOWN:
        if(type.id()==ID_string)
        {
            mp_integer int_value=binary2integer(value, false);
            irep_idt s;
            if(int_value>=string_numbering.size())
                s=irep_idt();
            else
                s=string_numbering[int_value.to_long()];

            return constant_exprt(s, type);
        }
        break;

    case IS_RANGE:
    {
        mp_integer int_value=binary2integer(value, false);
        mp_integer from=string2integer(type.get_string(ID_from));

        constant_exprt value_expr(type);
        value_expr.set_value(integer2string(int_value+from));
        return value_expr;
    }
    break;

    default:
    case IS_C_ENUM:
        constant_exprt value_expr(type);
        value_expr.set_value(value);
        return value_expr;
    }

    return nil_exprt();
}
Beispiel #22
0
void cpp_typecheckt::typecheck_type(typet &type)
{
  assert(type.id() != "");
  assert(type.is_not_nil());

  try
  {
    cpp_convert_plain_type(type);
  }

  catch(const char *error)
  {
    err_location(type);
    str << error;
    throw 0;
  }

  catch(const std::string &error)
  {
    err_location(type);
    str << error;
    throw 0;
  }

  if(type.id() == "cpp-name")
  {
    c_qualifierst qualifiers(type);

    cpp_namet cpp_name;
    cpp_name.swap(type);

    exprt symbol_expr =
      resolve(cpp_name, cpp_typecheck_resolvet::TYPE, cpp_typecheck_fargst());

    if(symbol_expr.id() != "type")
    {
      err_location(type);
      str << "error: expected type";
      throw 0;
    }

    type = symbol_expr.type();
    assert(type.is_not_nil());

    if(type.cmt_constant())
      qualifiers.is_constant = true;

    qualifiers.write(type);
  }
  else if(type.id() == "struct" || type.id() == "union")
  {
    typecheck_compound_type(type);
  }
  else if(type.id() == "pointer")
  {
    // the pointer might have a qualifier, but do subtype first
    typecheck_type(type.subtype());

    // Check if it is a pointer-to-member
    if(type.find("to-member").is_not_nil())
    {
      // these can point either to data members or member functions
      // of a class

      typet &class_object = static_cast<typet &>(type.add("to-member"));

      if(class_object.id() == "cpp-name")
      {
        assert(class_object.get_sub().back().id() == "::");
        class_object.get_sub().pop_back();
      }

      typecheck_type(class_object);

      // there may be arguments if this is a pointer to member function
      if(type.subtype().id() == "code")
      {
        irept::subt &args = type.subtype().add("arguments").get_sub();

        if(args.empty() || args.front().cmt_base_name() != "this")
        {
          // Add 'this' to the arguments
          exprt a0("argument");
          a0.cmt_base_name("this");
          a0.type().id("pointer");
          a0.type().subtype() = class_object;
          args.insert(args.begin(), a0);
        }
      }
    }

    // now do qualifier
    if(type.find("#qualifier").is_not_nil())
    {
      typet &t = static_cast<typet &>(type.add("#qualifier"));
      cpp_convert_plain_type(t);
      c_qualifierst q(t);
      q.write(type);
    }

    type.remove("#qualifier");
  }
  else if(type.id() == "array")
  {
    exprt &size_expr = to_array_type(type).size();

    if(size_expr.is_nil())
      type.id("incomplete_array");
    else
      typecheck_expr(size_expr);

    // TODO: If is a incomplete_array, it should always
    // have initializers, except for catch declaration

    typecheck_type(type.subtype());

    if(type.subtype().cmt_constant())
      type.cmt_constant(true);

    if(type.subtype().cmt_volatile())
      type.set("#volatile", true);
  }
  else if(type.id() == "code")
  {
    code_typet &code_type = to_code_type(type);
    typecheck_type(code_type.return_type());

    code_typet::argumentst &arguments = code_type.arguments();

    for(auto &argument : arguments)
    {
      typecheck_type(argument.type());

      // see if there is a default value
      if(argument.has_default_value())
      {
        typecheck_expr(argument.default_value());
        implicit_typecast(argument.default_value(), argument.type());
      }
    }
  }
  else if(type.id() == "template")
  {
    typecheck_type(type.subtype());
  }
  else if(type.id() == "c_enum")
  {
    typecheck_enum_type(type);
  }
  else if(
    type.id() == "unsignedbv" || type.id() == "signedbv" ||
    type.id() == "bool" || type.id() == "floatbv" || type.id() == "fixedbv" ||
    type.id() == "empty")
  {
  }
  else if(type.id() == "symbol")
  {
  }
  else if(type.id() == "constructor" || type.id() == "destructor")
  {
  }
  else if(type.id() == "cpp-cast-operator")
  {
  }
  else if(type.id() == "cpp-template-type")
  {
  }
  else if(type.id() == "typeof")
  {
    exprt e = static_cast<const exprt &>(type.find("expr"));

    if(e.is_nil())
    {
      typet tmp_type = static_cast<const typet &>(type.find("sizeof-type"));

      if(tmp_type.id() == "cpp-name")
      {
        // this may be ambiguous -- it can be either a type or
        // an expression

        cpp_typecheck_fargst fargs;

        exprt symbol_expr = resolve(
          to_cpp_name(static_cast<const irept &>(tmp_type)),
          cpp_typecheck_resolvet::BOTH,
          fargs);

        type = symbol_expr.type();
      }
      else
      {
        typecheck_type(tmp_type);
        type = tmp_type;
      }
    }
    else
    {
      typecheck_expr(e);
      type = e.type();
    }
  }
  else if(type.id() == "decltype")
  {
    exprt e = static_cast<const exprt &>(type.find("expr_arg"));
    typecheck_expr(e);
    type = e.type();
  }
  else if(type.id() == "unassigned")
  {
    // ignore, for template argument guessing
  }
  else if(type.id() == "ellipsis")
  {
  }
  else
  {
    err_location(type);
    str << "unexpected type: " << type.pretty();
    throw 0;
  }

  assert(type.is_not_nil());
}
bool boolbvt::type_conversion(
  const typet &src_type, const bvt &src,
  const typet &dest_type, bvt &dest)
{
  bvtypet dest_bvtype=get_bvtype(dest_type);
  bvtypet src_bvtype=get_bvtype(src_type);
  
  if(src_bvtype==IS_C_BIT_FIELD)
    return type_conversion(
      c_bit_field_replacement_type(to_c_bit_field_type(src_type), ns), src, dest_type, dest);

  if(dest_bvtype==IS_C_BIT_FIELD)
    return type_conversion(
      src_type, src, c_bit_field_replacement_type(to_c_bit_field_type(dest_type), ns), dest);

  std::size_t src_width=src.size();
  std::size_t dest_width=boolbv_width(dest_type);
  
  if(dest_width==0 || src_width==0)
    return true;
  
  dest.clear();
  dest.reserve(dest_width);

  if(dest_type.id()==ID_complex)
  {
    if(src_type==dest_type.subtype())
    {
      forall_literals(it, src)
      dest.push_back(*it);

      // pad with zeros
      for(std::size_t i=src.size(); i<dest_width; i++)
        dest.push_back(const_literal(false));

      return false;
    }
    else if(src_type.id()==ID_complex)
    {
      // recursively do both halfs
      bvt lower, upper, lower_res, upper_res;
      lower.assign(src.begin(), src.begin()+src.size()/2);
      upper.assign(src.begin()+src.size()/2, src.end());
      type_conversion(ns.follow(src_type.subtype()), lower, ns.follow(dest_type.subtype()), lower_res);
      type_conversion(ns.follow(src_type.subtype()), upper, ns.follow(dest_type.subtype()), upper_res);
      assert(lower_res.size()+upper_res.size()==dest_width);
      dest=lower_res;
      dest.insert(dest.end(), upper_res.begin(), upper_res.end());
      return false;
    }
  }
  
  if(src_type.id()==ID_complex)
  {
    assert(dest_type.id()!=ID_complex);
    if(dest_type.id()==ID_signedbv ||
       dest_type.id()==ID_unsignedbv ||
       dest_type.id()==ID_floatbv ||
       dest_type.id()==ID_fixedbv ||
       dest_type.id()==ID_c_enum ||
       dest_type.id()==ID_c_enum_tag ||
       dest_type.id()==ID_bool)
    {
      // A cast from complex x to real T
      // is (T) __real__ x.
      bvt tmp_src(src);
      tmp_src.resize(src.size()/2); // cut off imag part
      return type_conversion(src_type.subtype(), tmp_src, dest_type, dest);
    }
  }
  
  switch(dest_bvtype)
  {
  case IS_RANGE:
    if(src_bvtype==IS_UNSIGNED ||
       src_bvtype==IS_SIGNED ||
       src_bvtype==IS_C_BOOL)
    {
      mp_integer dest_from=to_range_type(dest_type).get_from();

      if(dest_from==0)
      {
        // do zero extension
        dest.resize(dest_width);
        for(std::size_t i=0; i<dest.size(); i++)
          dest[i]=(i<src.size()?src[i]:const_literal(false));

        return false;
      }
    }
    else if(src_bvtype==IS_RANGE) // range to range
    {
      mp_integer src_from=to_range_type(src_type).get_from();
      mp_integer dest_from=to_range_type(dest_type).get_from();

      if(dest_from==src_from)
      {
        // do zero extension, if needed
        dest=bv_utils.zero_extension(src, dest_width);
        return false;
      }
      else
      {
        // need to do arithmetic: add src_from-dest_from
        mp_integer offset=src_from-dest_from;
        dest=
          bv_utils.add(
            bv_utils.zero_extension(src, dest_width),
            bv_utils.build_constant(offset, dest_width));
      }

      return false;
    }
    break;
    
  case IS_FLOAT: // to float
    {
      float_utilst float_utils(prop);
      
      switch(src_bvtype)
      {
      case IS_FLOAT: // float to float
        // we don't have a rounding mode here,
        // which is why we refuse.
        break;

      case IS_SIGNED: // signed to float
      case IS_C_ENUM:
        float_utils.spec=to_floatbv_type(dest_type);
        dest=float_utils.from_signed_integer(src);
        return false;

      case IS_UNSIGNED: // unsigned to float
      case IS_C_BOOL: // _Bool to float
        float_utils.spec=to_floatbv_type(dest_type);
        dest=float_utils.from_unsigned_integer(src);
        return false;

      case IS_BV:
        assert(src_width==dest_width);
        dest=src;
        return false;

      default:
        if(src_type.id()==ID_bool)
        {
          // bool to float
          
          // build a one
          ieee_floatt f;
          f.spec=to_floatbv_type(dest_type);
          f.from_integer(1);
          
          dest=convert_bv(f.to_expr());

          assert(src_width==1);
          
          Forall_literals(it, dest)
            *it=prop.land(*it, src[0]);
            
          return false;
        }
      }
    }
    break;

  case IS_FIXED:
    if(src_bvtype==IS_FIXED)
    {
      // fixed to fixed
      
      std::size_t dest_fraction_bits=to_fixedbv_type(dest_type).get_fraction_bits(),
                  dest_int_bits=dest_width-dest_fraction_bits;
      std::size_t op_fraction_bits=to_fixedbv_type(src_type).get_fraction_bits(),
                  op_int_bits=src_width-op_fraction_bits;
      
      dest.resize(dest_width);
      
      // i == position after dot
      // i == 0: first position after dot

      for(std::size_t i=0; i<dest_fraction_bits; i++)
      {
        // position in bv
        std::size_t p=dest_fraction_bits-i-1;
      
        if(i<op_fraction_bits)
          dest[p]=src[op_fraction_bits-i-1];
        else 
          dest[p]=const_literal(false); // zero padding
      }

      for(std::size_t i=0; i<dest_int_bits; i++)
      {
        // position in bv
        std::size_t p=dest_fraction_bits+i;
        assert(p<dest_width);
      
        if(i<op_int_bits)
          dest[p]=src[i+op_fraction_bits];
        else 
          dest[p]=src[src_width-1]; // sign extension
      }

      return false;
    }
    else if(src_bvtype==IS_BV)
    {
      assert(src_width==dest_width);
      dest=src;
      return false;
    }
    else if(src_bvtype==IS_UNSIGNED ||
            src_bvtype==IS_SIGNED ||
            src_bvtype==IS_C_BOOL ||
            src_bvtype==IS_C_ENUM)
    {
      // integer to fixed

      std::size_t dest_fraction_bits=
        to_fixedbv_type(dest_type).get_fraction_bits();

      for(std::size_t i=0; i<dest_fraction_bits; i++)
        dest.push_back(const_literal(false)); // zero padding

      for(std::size_t i=0; i<dest_width-dest_fraction_bits; i++)
      {
        literalt l;
      
        if(i<src_width)
          l=src[i];
        else
        {
          if(src_bvtype==IS_SIGNED || src_bvtype==IS_C_ENUM)
            l=src[src_width-1]; // sign extension
          else
            l=const_literal(false); // zero extension
        }
        
        dest.push_back(l);
      }

      return false;
    }
    else if(src_type.id()==ID_bool)
    {
      // bool to fixed
      std::size_t fraction_bits=
        to_fixedbv_type(dest_type).get_fraction_bits();

      assert(src_width==1);

      for(std::size_t i=0; i<dest_width; i++)
      {
        if(i==fraction_bits)
          dest.push_back(src[0]);
        else
          dest.push_back(const_literal(false));
      }

      return false;
    }
    break;
  
  case IS_UNSIGNED:
  case IS_SIGNED:
  case IS_C_ENUM:
    switch(src_bvtype)
    {
    case IS_FLOAT: // float to integer
      // we don't have a rounding mode here,
      // which is why we refuse.
      break;
     
    case IS_FIXED: // fixed to integer
      {
        std::size_t op_fraction_bits=
          to_fixedbv_type(src_type).get_fraction_bits();

        for(std::size_t i=0; i<dest_width; i++)
        {
          if(i<src_width-op_fraction_bits)
            dest.push_back(src[i+op_fraction_bits]);
          else
          {
            if(dest_bvtype==IS_SIGNED)
              dest.push_back(src[src_width-1]); // sign extension
            else
              dest.push_back(const_literal(false)); // zero extension
          }
        }
        
        // we might need to round up in case of negative numbers
        // e.g., (int)(-1.00001)==1
        
        bvt fraction_bits_bv=src;
        fraction_bits_bv.resize(op_fraction_bits);
        literalt round_up=
          prop.land(prop.lor(fraction_bits_bv), src.back());

        dest=bv_utils.incrementer(dest, round_up);

        return false;
      }

    case IS_UNSIGNED: // integer to integer
    case IS_SIGNED:
    case IS_C_ENUM:
    case IS_C_BOOL:
      {
        // We do sign extension for any source type
        // that is signed, independently of the
        // destination type.
        // E.g., ((short)(ulong)(short)-1)==-1
        bool sign_extension=
          src_bvtype==IS_SIGNED || src_bvtype==IS_C_ENUM;

        for(std::size_t i=0; i<dest_width; i++)
        {
          if(i<src_width)
            dest.push_back(src[i]);
          else if(sign_extension)
            dest.push_back(src[src_width-1]); // sign extension
          else
            dest.push_back(const_literal(false));
        }

        return false;
      }
      
    case IS_VERILOG_UNSIGNED: // verilog_unsignedbv to signed/unsigned/enum
      {
        for(std::size_t i=0; i<dest_width; i++)
        {
          std::size_t src_index=i*2; // we take every second bit

          if(src_index<src_width)
            dest.push_back(src[src_index]);
          else // always zero-extend
            dest.push_back(const_literal(false));
        }

        return false;
      }
      break;
      
    case IS_VERILOG_SIGNED: // verilog_signedbv to signed/unsigned/enum
      {
        for(std::size_t i=0; i<dest_width; i++)
        {
          std::size_t src_index=i*2; // we take every second bit

          if(src_index<src_width)
            dest.push_back(src[src_index]);
          else // always sign-extend
            dest.push_back(src.back());
        }

        return false;
      }
      break;
      
    default:
      if(src_type.id()==ID_bool)
      {
        // bool to integer

        assert(src_width==1);

        for(std::size_t i=0; i<dest_width; i++)
        {
          if(i==0)
            dest.push_back(src[0]);
          else
            dest.push_back(const_literal(false));
        }

        return false;
      }
    }
    break;
    
  case IS_VERILOG_UNSIGNED:
    if(src_bvtype==IS_UNSIGNED ||
       src_bvtype==IS_C_BOOL ||
       src_type.id()==ID_bool)
    {
      for(std::size_t i=0, j=0; i<dest_width; i+=2, j++)
      {
        if(j<src_width)
          dest.push_back(src[j]);
        else
          dest.push_back(const_literal(false));

        dest.push_back(const_literal(false));
      }

      return false;
    }
    else if(src_bvtype==IS_SIGNED)
    {
      for(std::size_t i=0, j=0; i<dest_width; i+=2, j++)
      {
        if(j<src_width)
          dest.push_back(src[j]);
        else
          dest.push_back(src.back());

        dest.push_back(const_literal(false));
      }

      return false;
    }
    else if(src_bvtype==IS_VERILOG_UNSIGNED)
    {
      // verilog_unsignedbv to verilog_unsignedbv
      dest=src;

      if(dest_width<src_width)
        dest.resize(dest_width);
      else
      {
        dest=src;
        while(dest.size()<dest_width)
        {
          dest.push_back(const_literal(false));
          dest.push_back(const_literal(false));
        }
      }
      return false;
    }
    break;

  case IS_BV:
    assert(src_width==dest_width);
    dest=src;
    return false;
    
  case IS_C_BOOL:
    dest.resize(dest_width, const_literal(false));

    if(src_bvtype==IS_FLOAT)
    {
      float_utilst float_utils(prop);
      float_utils.spec=to_floatbv_type(src_type);
      dest[0]=!float_utils.is_zero(src);
    }
    else if(src_bvtype==IS_C_BOOL)
      dest[0]=src[0];
    else
      dest[0]=!bv_utils.is_zero(src);

    return false;
    
  default:
    if(dest_type.id()==ID_array)
    {
      if(src_width==dest_width)
      {
        dest=src;
        return false;
      }
    }
    else if(dest_type.id()==ID_struct)
    {
      const struct_typet &dest_struct =
        to_struct_type(dest_type);

      if(src_type.id()==ID_struct)
      {
        // we do subsets

        dest.resize(dest_width, const_literal(false));

        const struct_typet &op_struct =
          to_struct_type(src_type);

        const struct_typet::componentst &dest_comp=
          dest_struct.components();

        const struct_typet::componentst &op_comp=
          op_struct.components();

        // build offset maps
        offset_mapt op_offsets, dest_offsets;

        build_offset_map(op_struct, op_offsets);
        build_offset_map(dest_struct, dest_offsets);

        // build name map
        typedef std::map<irep_idt, unsigned> op_mapt;
        op_mapt op_map;

        for(std::size_t i=0; i<op_comp.size(); i++)
          op_map[op_comp[i].get_name()]=i;

        // now gather required fields
        for(std::size_t i=0;
            i<dest_comp.size();
            i++)
        {
          std::size_t offset=dest_offsets[i];
          std::size_t comp_width=boolbv_width(dest_comp[i].type());
          if(comp_width==0) continue;

          op_mapt::const_iterator it=
            op_map.find(dest_comp[i].get_name());

          if(it==op_map.end())
          {
            // not found

            // filling with free variables
            for(std::size_t j=0; j<comp_width; j++)
              dest[offset+j]=prop.new_variable();
          }
          else
          {
            // found
            if(dest_comp[i].type()!=dest_comp[it->second].type())
            {
              // filling with free variables
              for(std::size_t j=0; j<comp_width; j++)
                dest[offset+j]=prop.new_variable();
            }
            else
            {
              std::size_t op_offset=op_offsets[it->second];
              for(std::size_t j=0; j<comp_width; j++)
                dest[offset+j]=src[op_offset+j];
            }
          }
        }

        return false;
      }
    }

  }

  return true;
}
Beispiel #24
0
xmlt xml(
  const typet &type,
  const namespacet &ns)
{
  if(type.id()==ID_symbol)
    return xml(ns.follow(type), ns);

  xmlt result;

  if(type.id()==ID_unsignedbv)
  {
    result.name="integer";
    result.set_attribute("width", to_unsignedbv_type(type).get_width());
  }
  else if(type.id()==ID_signedbv)
  {
    result.name="integer";
    result.set_attribute("width", to_signedbv_type(type).get_width());
  }
  else if(type.id()==ID_floatbv)
  {
    result.name="float";
    result.set_attribute("width", to_floatbv_type(type).get_width());
  }
  else if(type.id()==ID_bv)
  {
    result.name="integer";
    result.set_attribute("width", to_bv_type(type).get_width());
  }
  else if(type.id()==ID_c_bit_field)
  {
    result.name="integer";
    result.set_attribute("width", to_c_bit_field_type(type).get_width());
  }
  else if(type.id()==ID_c_enum_tag)
  {
    // we return the base type
    return xml(ns.follow_tag(to_c_enum_tag_type(type)).subtype(), ns);
  }
  else if(type.id()==ID_fixedbv)
  {
    result.name="fixed";
    result.set_attribute("width", to_fixedbv_type(type).get_width());
  }
  else if(type.id()==ID_pointer)
  {
    result.name="pointer";
    result.new_element("subtype").new_element()=xml(type.subtype(), ns);
  }
  else if(type.id()==ID_bool)
  {
    result.name="boolean";
  }
  else if(type.id()==ID_array)
  {
    result.name="array";
    result.new_element("subtype").new_element()=xml(type.subtype(), ns);
  }
  else if(type.id()==ID_vector)
  {
    result.name="vector";
    result.new_element("subtype").new_element()=xml(type.subtype(), ns);
    result.new_element("size").new_element()=xml(to_vector_type(type).size(), ns);
  }
  else if(type.id()==ID_struct)
  {
    result.name="struct";
    const struct_typet::componentst &components=
      to_struct_type(type).components();
    for(struct_typet::componentst::const_iterator
        it=components.begin(); it!=components.end(); it++)
    {
      xmlt &e=result.new_element("member");
      e.set_attribute("name", id2string(it->get_name()));
      e.new_element("type").new_element()=xml(it->type(), ns);
    }
  }
  else if(type.id()==ID_union)
  {
    result.name="union";
    const union_typet::componentst &components=
      to_union_type(type).components();
    for(union_typet::componentst::const_iterator
        it=components.begin(); it!=components.end(); it++)
    {
      xmlt &e=result.new_element("member");
      e.set_attribute("name", id2string(it->get_name()));
      e.new_element("type").new_element()=xml(it->type(), ns);
    }
  }
  else
    result.name="unknown";

  return result;
}
Beispiel #25
0
bool smt1_dect::string_to_expr_z3(
  const typet &type,
  const std::string &value,
  exprt &e) const
{
  if(value.substr(0,2)=="bv")
  {
    std::string v=value.substr(2, value.find('[')-2);
    size_t p = value.find('[')+1;
    std::string w=value.substr(p, value.find(']')-p);

    std::string binary=integer2binary(string2integer(v,10),
                                      string2integer(w,10).to_ulong());

    if(type.id()==ID_struct)
    {
      e=binary2struct(to_struct_type(type), binary);
    }
    else if(type.id()==ID_union)
    {
      e=binary2union(to_union_type(type), binary);
    }
    else
    {
      constant_exprt c(type);
      c.set_value(binary);
      e=c;
    }

    return true;
  }
  else if(value.substr(0,6)=="(const") // const arrays
  {
    std::string av = value.substr(7, value.length()-8);

    exprt ae;
    if(!string_to_expr_z3(type.subtype(), av, ae)) return false;

    array_of_exprt ao;
    ao.type() = typet("array");
    ao.type().subtype()=ae.type();
    ao.what() = ae;

    e = ao;

    return true;
  }
  else if(value.substr(0,6)=="(store")
  {
    size_t p1=value.rfind(' ')+1;
    size_t p2=value.rfind(' ', p1-2)+1;

    assert(p1!=std::string::npos && p2!=std::string::npos);

    std::string elem = value.substr(p1, value.size()-p1-1);
    std::string inx = value.substr(p2, p1-p2-1);
    std::string array = value.substr(7, p2-8);

    exprt old;
    if(!string_to_expr_z3(type, array, old)) return false;

    exprt where;
    if(!string_to_expr_z3(array_index_type(), inx, where)) return false;

    exprt new_val;
    if(!string_to_expr_z3(type.subtype(), elem, new_val)) return false;

    e = with_exprt(old, where, new_val);

    return true;
  }
  else if(value=="false")
  {
    e = false_exprt();
    return true;
  }
  else if(value=="true")
  {
    e = true_exprt();
    return true;
  }
  else if(value.substr(0,8)=="array_of")
  {
    // We assume that array_of has only concrete arguments...
    irep_idt id(value);
    array_of_mapt::const_iterator fit=array_of_map.begin();
    while(fit!=array_of_map.end() && fit->second!=id) fit++;

    if(fit==array_of_map.end()) return false;

    e = fit->first;

    return true;
  }
  else if(type.id()==ID_rational)
  {
    constant_exprt result;
    result.type()=rational_typet();

    if(value.substr(0,4)=="val!")
      result.set_value(value.substr(4));
    else
      result.set_value(value);

    e = result;
    return true;
  }

  return false;
}
Beispiel #26
0
bool cpp_typecheckt::cpp_is_pod(const typet &type) const
{
  if(type.id()==ID_struct)
  {
    // Not allowed in PODs:
    // * Non-PODs
    // * Constructors/Destructors
    // * virtuals
    // * private/protected, unless static
    // * overloading assignment operator
    // * Base classes

    const struct_typet &struct_type=to_struct_type(type);

    if(!type.find(ID_bases).get_sub().empty())
      return false;

    const struct_typet::componentst &components=
      struct_type.components();

    for(struct_typet::componentst::const_iterator
        it=components.begin();
        it!=components.end();
        it++)
    {
      if(it->get_bool(ID_is_type))
        continue;

      if(it->get_base_name()=="operator=")
        return false;

      if(it->get_bool(ID_is_virtual))
        return false;

      const typet &sub_type=it->type();

      if(sub_type.id()==ID_code)
      {
        if(it->get_bool(ID_is_virtual))
          return false;

        const typet &return_type=to_code_type(sub_type).return_type();

        if(return_type.id()==ID_constructor ||
           return_type.id()==ID_destructor)
          return false;
      }
      else if(it->get(ID_access)!=ID_public &&
              !it->get_bool(ID_is_static))
        return false;

      if(!cpp_is_pod(sub_type))
        return false;
    }

    return true;
  }
  else if(type.id()==ID_array)
  {
    return cpp_is_pod(type.subtype());
  }
  else if(type.id()==ID_pointer)
  {
    if(is_reference(type)) // references are not PODs
      return false;

    // but pointers are PODs!
    return true;
  }
  else if(type.id()==ID_symbol)
  {
    const symbolt &symb=lookup(type.get(ID_identifier));
    assert(symb.is_type);
    return cpp_is_pod(symb.type);
  }

  // everything else is POD
  return true;
}
Beispiel #27
0
void c_typecastt::implicit_typecast_followed(
  exprt &expr,
  const typet &src_type,
  const typet &dest_type)
{
  if(dest_type.id()==ID_union)

  // do transparent union
  if(dest_type.id()==ID_union &&
     dest_type.get_bool(ID_C_transparent_union) &&
     src_type.id()!=ID_union)
  {
    // The argument corresponding to a transparent union type can be of any
    // type in the union; no explicit cast is required.
    
    // Check union members.
    const union_typet &dest_union_type=to_union_type(dest_type);

    for(union_typet::componentst::const_iterator
        it=dest_union_type.components().begin();
        it!=dest_union_type.components().end();
        it++)
    {
      if(!check_c_implicit_typecast(src_type, it->type()))
      {
        // build union constructor
        exprt union_expr(ID_union, dest_union_type);
        union_expr.move_to_operands(expr);
        union_expr.set(ID_component_name, it->get_name());
        expr=union_expr;
        return; // ok
      }
    }
  }

  if(dest_type.id()==ID_pointer)
  {
    // special case: 0 == NULL

    if(expr.is_zero() && (
       src_type.id()==ID_unsignedbv ||
       src_type.id()==ID_signedbv ||
       src_type.id()==ID_natural ||
       src_type.id()==ID_integer))
    {
      expr=exprt(ID_constant, dest_type);
      expr.set(ID_value, ID_NULL);
      return; // ok
    }
  
    if(src_type.id()==ID_pointer ||
       src_type.id()==ID_array)
    {
      // we are quite generous about pointers
      
      const typet &src_sub=ns.follow(src_type.subtype());
      const typet &dest_sub=ns.follow(dest_type.subtype());

      if(is_void_pointer(src_type) ||
         is_void_pointer(dest_type))
      {
        // from/to void is always good
      }
      else if(src_sub.id()==ID_code &&
              dest_sub.id()==ID_code)
      {
        // very generous:
        // between any two function pointers it's ok
      }
      else if(base_type_eq(src_type.subtype(), dest_type.subtype(), ns))
      {
        // ok
      }
      else if((is_number(src_sub) || src_sub.id()==ID_c_enum) &&
              (is_number(dest_sub) || dest_sub.id()==ID_c_enum))
      {
        // Also generous: between any to scalar types it's ok.
        // We should probably check the size.
      }
      else
        warnings.push_back("incompatible pointer types");

      // check qualifiers

      /*
      if(src_type.subtype().get_bool(ID_C_constant) &&
         !dest_type.subtype().get_bool(ID_C_constant))
        warnings.push_back("disregarding const");
      */

      if(src_type.subtype().get_bool(ID_C_volatile) &&
         !dest_type.subtype().get_bool(ID_C_volatile))
        warnings.push_back("disregarding volatile");

      if(src_type==dest_type)
      {
        expr.type()=src_type; // because of qualifiers
      }
      else
        do_typecast(expr, dest_type);

      return; // ok
    }
  }
  
  if(check_c_implicit_typecast(src_type, dest_type))
    errors.push_back("implicit conversion not permitted");
  else if(src_type!=dest_type)
    do_typecast(expr, dest_type);
}
Beispiel #28
0
unsigned interpretert::get_size(const typet &type) const
{
  if(type.id()==ID_struct)
  {
    const struct_typet::componentst &components=
      to_struct_type(type).components();

    unsigned sum=0;

    for(struct_typet::componentst::const_iterator
        it=components.begin();
        it!=components.end();
        it++)
    {
      const typet &sub_type=it->type();

      if(sub_type.id()!=ID_code)
        sum+=get_size(sub_type);
    }
    
    return sum;
  }
  else if(type.id()==ID_union)
  {
    const union_typet::componentst &components=
      to_union_type(type).components();

    unsigned max_size=0;

    for(union_typet::componentst::const_iterator
        it=components.begin();
        it!=components.end();
        it++)
    {
      const typet &sub_type=it->type();

      if(sub_type.id()!=ID_code)
        max_size=std::max(max_size, get_size(sub_type));
    }

    return max_size;    
  }
  else if(type.id()==ID_array)
  {
    const exprt &size_expr=static_cast<const exprt &>(type.find(ID_size));

    unsigned subtype_size=get_size(type.subtype());

    mp_integer i;
    if(!to_integer(size_expr, i))
      return subtype_size*integer2unsigned(i);
    else
      return subtype_size;
  }
  else if(type.id()==ID_symbol)
  {
    return get_size(ns.follow(type));
  }
  else
    return 1;
}
Beispiel #29
0
void cpp_typecheckt::typecheck_enum_type(typet &type)
{
  // first save qualifiers
  c_qualifierst qualifiers;
  qualifiers.read(type);
  
  cpp_enum_typet &enum_type=to_cpp_enum_type(type);
  bool anonymous=!enum_type.has_tag();
  irep_idt base_name;
  
  if(anonymous)
  {
    // we fabricate a tag based on the enum constants contained
    base_name=enum_type.generate_anon_tag();
  }
  else
  {
    const cpp_namet &tag=enum_type.tag();
    
    if(tag.is_simple_name())
      base_name=tag.get_base_name();
    else
    {
      err_location(type);
      throw "enum tag is expected to be a simple name";
    }
  }

  bool has_body=enum_type.has_body();
  bool tag_only_declaration=enum_type.get_tag_only_declaration();

  cpp_scopet &dest_scope=
    tag_scope(base_name, has_body, tag_only_declaration);

  const irep_idt symbol_name=
    dest_scope.prefix+"tag-"+id2string(base_name);

  // check if we have it
  
  symbol_tablet::symbolst::iterator previous_symbol=
    symbol_table.symbols.find(symbol_name);
    
  if(previous_symbol!=symbol_table.symbols.end())
  {
    // we do!

    symbolt &symbol=previous_symbol->second;

    if(has_body)
    {
      err_location(type);
      str << "error: enum symbol `" << base_name
          << "' declared previously\n";
      str << "location of previous definition: "
          << symbol.location;
      throw 0;
    }
  }
  else if(has_body)
  {
    std::string pretty_name=
      cpp_scopes.current_scope().prefix+id2string(base_name);
      
    // C++11 enumerations have an underlying type,
    // which defaults to int.
    // enums without underlying type may be 'packed'.
    if(type.subtype().is_nil())
      type.subtype()=signed_int_type();
    else
    {
      typecheck_type(type.subtype());
      if(type.subtype().id()==ID_signedbv ||
         type.subtype().id()==ID_unsignedbv)
      {
      }
      else
      {
        err_location(type);
        str << "underlying type must be integral";
        throw 0;
      }
    }

    symbolt symbol;

    symbol.name=symbol_name;
    symbol.base_name=base_name;
    symbol.value.make_nil();
    symbol.location=type.source_location();
    symbol.mode=ID_cpp;
    symbol.module=module;
    symbol.type.swap(type);
    symbol.is_type=true;
    symbol.is_macro=false;
    symbol.pretty_name=pretty_name;
    
    // move early, must be visible before doing body
    symbolt *new_symbol;
    if(symbol_table.move(symbol, new_symbol))
      throw "cpp_typecheckt::typecheck_enum_type: symbol_table.move() failed";    

    // put into scope
    cpp_idt &scope_identifier=
      cpp_scopes.put_into_scope(*new_symbol, dest_scope);
    
    scope_identifier.id_class=cpp_idt::CLASS;

    typecheck_enum_body(*new_symbol);
  }
  else
  {
    err_location(type);
    str << "use of enum `" << base_name
        << "' without previous declaration";
    throw 0;
  }

  // create enum tag expression, and add the qualifiers
  type=c_enum_tag_typet(symbol_name);
  qualifiers.write(type);
}
Beispiel #30
0
std::string type2name(const typet &type)
{
  std::string result;
  
  // qualifiers first
  if(type.get_bool(ID_C_constant))
    result+="c";

  if(type.get_bool(ID_C_restricted))
    result+="r";

  if(type.get_bool(ID_C_volatile))
    result+="v";

  if(type.id()==irep_idt())
    throw "Empty type encountered.";
  else if(type.id()==ID_empty)
    result+="V";   
  else if(type.id()==ID_signedbv)
    result+="S" + type.get_string(ID_width);
  else if(type.id()==ID_unsignedbv)
    result+="U" + type.get_string(ID_width);
  else if(type.id()==ID_bool) 
    result+="B";
  else if(type.id()==ID_integer) 
    result+="I";
  else if(type.id()==ID_real) 
    result+="R";
  else if(type.id()==ID_complex) 
    result+="C";
  else if(type.id()==ID_floatbv) 
    result+="F" + type.get_string(ID_width);
  else if(type.id()==ID_fixedbv) 
    result+="X" + type.get_string(ID_width);
  else if(type.id()==ID_natural)
    result+="N";
  else if(type.id()==ID_pointer)
    result+="*";
  else if(type.id()==ID_reference)
    result+="&";
  else if(type.id()==ID_code)
  {
    const code_typet &t=to_code_type(type);
    const code_typet::argumentst arguments=t.arguments();
    result+="P(";

    for(code_typet::argumentst::const_iterator it=arguments.begin();
        it!=arguments.end();
        it++)
    {      
      result+=type2name(it->type());
      result+="'" + id2string(it->get_identifier()) + "'|";
    }
    result.resize(result.size()-1);
    result+=")";
  }
  else if(type.id()==ID_array)
  {
    const array_typet &t=to_array_type(type);
    if(t.size().is_nil())
      result+="ARR?";
    else
      result+="ARR"+t.size().get_string(ID_value);
  }
  else if(type.id()==ID_symbol)
  {
    result+="SYM#"+type.get_string(ID_identifier)+"#";
  }
  else if(type.id()==ID_struct || 
          type.id()==ID_union)
  {
    if(type.id()==ID_struct) result+="ST";
    if(type.id()==ID_union) result+="UN";
    const struct_union_typet &t=to_struct_union_type(type);
    const struct_union_typet::componentst &components = t.components();
    result+="[";
    for(struct_union_typet::componentst::const_iterator
        it=components.begin();
        it!=components.end();
        it++)
    {            
      if(it!=components.begin()) result+="|";
      result+=type2name(it->type());
      result+="'"+it->get_string(ID_name)+"'|";
    }
    result+="]";
  }
  else if(type.id()==ID_incomplete_struct)
    result +="ST?";
  else if(type.id()==ID_incomplete_union)
    result +="UN?";
  else if(type.id()==ID_c_enum)
    result +="EN"+type.get_string(ID_width);
  else if(type.id()==ID_incomplete_c_enum)
    result +="EN?";
  else if(type.id()==ID_c_bitfield)
    result+="BF"+type.get_string(ID_size);
  else if(type.id()==ID_vector)
    result+="VEC"+type.get_string(ID_size);
  else
    throw (std::string("Unknown type '") + 
           type.id_string() + 
           "' encountered."); 
    
  if(type.has_subtype())
  {
    result+="{";
    result+=type2name(type.subtype());    
    result+="}";
  }

  if(type.has_subtypes())
  {
    result+="$";
    forall_subtypes(it, type)
    {      
      result+=type2name(*it);
      result+="|";      
    }