Example #1
0
void c_typecheck_baset::designator_enter(
  const typet &type,
  designatort &designator)
{
  designatort::entryt entry;
  entry.type=type;

  assert(entry.type.id()!=ID_symbol);
  
  if(entry.type.id()==ID_struct)
  {
    entry.size=to_struct_type(entry.type).components().size();

    if(entry.size!=0)
      entry.subtype=to_struct_type(entry.type).components().front().type();
    else
      entry.subtype.make_nil();
  }
  else if(entry.type.id()==ID_union)
  {
    if(to_union_type(entry.type).components().empty())
    {
      entry.size=0;
      entry.subtype.make_nil();
    }
    else
    {
      entry.size=1;
      entry.subtype=to_union_type(entry.type).components().front().type();
    }
  }
  else if(entry.type.id()==ID_array)
  {
    mp_integer array_size;

    if(to_integer(to_array_type(entry.type).size(), array_size))
    {
      err_location(to_array_type(entry.type).size());
      str << "array has non-constant size `"
          << to_string(to_array_type(entry.type).size()) << "'";
      throw 0;
    }

    entry.size=integer2long(array_size);
    entry.subtype=entry.type.subtype();
  }
  else if(entry.type.id()==ID_incomplete_array)
  {
    entry.size=0;
    entry.subtype=entry.type.subtype();
  }
  else
    assert(false);

  designator.push_entry(entry);
}
Example #2
0
void boolbvt::convert_with(
  const typet &type,
  const exprt &op1,
  const exprt &op2,
  const bvt &prev_bv,
  bvt &next_bv)
{
  // we only do that on arrays, bitvectors, structs, and unions

  next_bv.resize(prev_bv.size());

  if(type.id()==ID_array)
    return convert_with_array(to_array_type(type), op1, op2, prev_bv, next_bv);
  else if(type.id()==ID_bv ||
          type.id()==ID_unsignedbv ||
          type.id()==ID_signedbv)
    return convert_with_bv(type, op1, op2, prev_bv, next_bv);
  else if(type.id()==ID_struct)
    return convert_with_struct(to_struct_type(type), op1, op2, prev_bv, next_bv);
  else if(type.id()==ID_union)
    return convert_with_union(to_union_type(type), op1, op2, prev_bv, next_bv);
  else if(type.id()==ID_symbol)
    return convert_with(ns.follow(type), op1, op2, prev_bv, next_bv);

  error().source_location=type.source_location();
  error() << "unexpected with type: " << type.id();
  throw 0;
}
Example #3
0
jsil_union_typet::jsil_union_typet(const std::vector<typet> &types):
    union_typet()
{
  auto &elements=components();
  for(const auto &type : types)
  {
    if(type.id()==ID_union)
    {
      for(const auto &component : to_union_type(type).components())
        elements.push_back(component);
    }
    else
      elements.push_back(componentt(ID_anonymous, type));
  }

  std::sort(elements.begin(), elements.end(), compare_components);
}
Example #4
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();
}
Example #5
0
void boolbvt::convert_update_rec(
  const exprt::operandst &designators,
  std::size_t d,
  const typet &type,
  std::size_t offset,
  const exprt &new_value,
  bvt &bv)
{
  if(type.id()==ID_symbol)
    convert_update_rec(
      designators, d, ns.follow(type), offset, new_value, bv);

  if(d>=designators.size())
  {
    // done
    bvt new_value_bv=convert_bv(new_value);
    std::size_t new_value_width=boolbv_width(type);
    
    if(new_value_width!=new_value_bv.size())
      throw "convert_update_rec: unexpected new_value size";

    // update
    for(std::size_t i=0; i<new_value_width; i++)
    {
      assert(offset+i<bv.size());
      bv[offset+i]=new_value_bv[i];
    }
    
    return;
  }

  const exprt &designator=designators[d];

  if(designator.id()==ID_index_designator)
  {
    if(type.id()!=ID_array)
      throw "update: index designator needs array";
      
    if(designator.operands().size()!=1)
      throw "update: index designator takes one operand";
      
    bvt index_bv=convert_bv(designator.op0());

    const array_typet &array_type=to_array_type(type);
    
    const typet &subtype=ns.follow(array_type.subtype());

    std::size_t element_size=boolbv_width(subtype);

    // iterate over array
    mp_integer size;
    if(to_integer(array_type.size(), size))
      throw "update: failed to get array size";
      
    bvt tmp_bv=bv;
    
    for(std::size_t i=0; i!=integer2long(size); ++i)
    {
      std::size_t new_offset=offset+i*element_size;
      
      convert_update_rec(
        designators, d+1, subtype, new_offset, new_value, tmp_bv);

      bvt const_bv=bv_utils.build_constant(i, index_bv.size());
      literalt equal=bv_utils.equal(const_bv, index_bv);

      for(std::size_t j=0; j<element_size; j++)
      {
        std::size_t idx=new_offset+j;
        assert(idx<bv.size());
        bv[idx]=prop.lselect(equal, tmp_bv[idx], bv[idx]);
      }
    }
  }
  else if(designator.id()==ID_member_designator)
  {
    const irep_idt &component_name=designator.get(ID_component_name);
  
    if(type.id()==ID_struct)
    {
      const struct_typet &struct_type=
        to_struct_type(type);

      std::size_t struct_offset=0;
      
      struct_typet::componentt component;
      component.make_nil();

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

      for(struct_typet::componentst::const_iterator
          it=components.begin();
          it!=components.end();
          it++)
      {
        const typet &subtype=it->type();
        std::size_t sub_width=boolbv_width(subtype);

        if(it->get_name()==component_name)
        {
          component=*it;
          break; // done
        }

        struct_offset+=sub_width;
      }
        
      if(component.is_nil())
        throw "update: failed to find struct component";

      const typet &new_type=ns.follow(component.type());

      std::size_t new_offset=offset+struct_offset;

      // recursive call
      convert_update_rec(
        designators, d+1, new_type, new_offset, new_value, bv);
    }
    else if(type.id()==ID_union)
    {
      const union_typet &union_type=
        to_union_type(type);

      const union_typet::componentt &component=
        union_type.get_component(component_name);
        
      if(component.is_nil())
        throw "update: failed to find union component";

      // this only adjusts the type, the offset stays as-is

      const typet &new_type=ns.follow(component.type());

      // recursive call
      convert_update_rec(
        designators, d+1, new_type, offset, new_value, bv);
    }
    else
      throw "update: member designator needs struct or union";
  }
  else
    throw "update: unexpected designator";
}
Example #6
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;
}
Example #7
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;
}
Example #8
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;
}
Example #9
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);
}
mp_integer pointer_offset_size(
  const namespacet &ns,
  const typet &type)
{
  if(type.id()==ID_array)
  {
    mp_integer sub=pointer_offset_size(ns, type.subtype());
  
    // get size
    const exprt &size=to_array_type(type).size();

    // constant?
    mp_integer i;
    
    if(to_integer(size, i))
      return -1; // we cannot distinguish the elements
    
    return sub*i;
  }
  else if(type.id()==ID_struct)
  {
    const struct_typet &struct_type=to_struct_type(type);
    const struct_typet::componentst &components=
      struct_type.components();
      
    mp_integer result=0;
    unsigned bit_field_bits=0;
    
    for(struct_typet::componentst::const_iterator
        it=components.begin();
        it!=components.end();
        it++)
    {
      if(it->get_is_bit_field())
      {
        bit_field_bits+=it->type().get_int(ID_width);
      }
      else
      {
        if(bit_field_bits!=0)
        {
          result+=bit_field_bits/8;
          bit_field_bits=0;
        }
        
        const typet &subtype=it->type();
        mp_integer sub_size=pointer_offset_size(ns, subtype);
        if(sub_size==-1) return -1;
        result+=sub_size;
      }
    }
    
    return result;
  }
  else if(type.id()==ID_union)
  {
    const union_typet &union_type=to_union_type(type);
    const union_typet::componentst &components=
      union_type.components();
      
    mp_integer result=0;

    // compute max
    
    for(union_typet::componentst::const_iterator
        it=components.begin();
        it!=components.end();
        it++)
    {
      const typet &subtype=it->type();
      mp_integer sub_size=pointer_offset_size(ns, subtype);
      if(sub_size>result) result=sub_size;
    }
    
    return result;
  }
  else if(type.id()==ID_signedbv ||
          type.id()==ID_unsignedbv ||
          type.id()==ID_fixedbv ||
          type.id()==ID_floatbv ||
          type.id()==ID_bv ||
          type.id()==ID_c_enum)
  {
    unsigned width=to_bitvector_type(type).get_width();
    unsigned bytes=width/8;
    if(bytes*8!=width) bytes++;
    return bytes;
  }
  else if(type.id()==ID_bool)
    return 1;
  else if(type.id()==ID_pointer)
  {
    unsigned width=config.ansi_c.pointer_width;
    unsigned bytes=width/8;
    if(bytes*8!=width) bytes++;
    return bytes;
  }
  else if(type.id()==ID_symbol)
    return pointer_offset_size(ns, ns.follow(type));
  else if(type.id()==ID_code)
    return 0;
  else
    return mp_integer(-1);
}
Example #11
0
const boolbv_widtht::entryt &boolbv_widtht::get_entry(const typet &type) const
{
  // check cache first

  std::pair<cachet::iterator, bool> cache_result=
    cache.insert(std::pair<typet, entryt>(type, entryt()));
    
  entryt &entry=cache_result.first->second;

  if(!cache_result.second) // found!
    return entry;
    
  entry.total_width=0;
  
  const irep_idt type_id=type.id();

  if(type_id==ID_struct)
  {
    const struct_typet::componentst &components=
      to_struct_type(type).components();

    std::size_t offset=0;
    entry.members.resize(components.size());
  
    for(std::size_t i=0; i<entry.members.size(); i++)
    {
      std::size_t sub_width=operator()(components[i].type());
      entry.members[i].offset=offset;
      entry.members[i].width=sub_width;
      offset+=sub_width;
    }
    
    entry.total_width=offset;
  }
  else if(type_id==ID_union)
  {
    const union_typet::componentst &components=
      to_union_type(type).components();

    entry.members.resize(components.size());
    
    std::size_t max_width=0;
  
    for(std::size_t i=0; i<entry.members.size(); i++)
    {
      std::size_t sub_width=operator()(components[i].type());
      entry.members[i].width=sub_width;
      max_width=std::max(max_width, sub_width);
    }

    entry.total_width=max_width;
  }
  else if(type_id==ID_bool)
    entry.total_width=1;
  else if(type_id==ID_c_bool)
  {
    entry.total_width=to_c_bool_type(type).get_width();
    assert(entry.total_width!=0);
  }
  else if(type_id==ID_signedbv)
  {
    entry.total_width=to_signedbv_type(type).get_width();
    assert(entry.total_width!=0);
  }
  else if(type_id==ID_unsignedbv)
  {
    entry.total_width=to_unsignedbv_type(type).get_width();
    assert(entry.total_width!=0);
  }
  else if(type_id==ID_floatbv)
  {
    entry.total_width=to_floatbv_type(type).get_width();
    assert(entry.total_width!=0);
  }
  else if(type_id==ID_fixedbv)
  {
    entry.total_width=to_fixedbv_type(type).get_width();
    assert(entry.total_width!=0);
  }
  else if(type_id==ID_bv)
  {
    entry.total_width=to_bv_type(type).get_width();
    assert(entry.total_width!=0);
  }
  else if(type_id==ID_verilogbv)
  {
    // we encode with two bits
    entry.total_width=type.get_unsigned_int(ID_width)*2;
    assert(entry.total_width!=0);
  }
  else if(type_id==ID_range)
  {
    mp_integer from=string2integer(type.get_string(ID_from)),
                 to=string2integer(type.get_string(ID_to));

    mp_integer size=to-from+1;

    if(size>=1)
    {
      entry.total_width=integer2unsigned(address_bits(size));
      assert(entry.total_width!=0);
    }
  }
  else if(type_id==ID_array)
  {
    const array_typet &array_type=to_array_type(type);
    std::size_t sub_width=operator()(array_type.subtype());

    mp_integer array_size;

    if(to_integer(array_type.size(), array_size))
    {
      // we can still use the theory of arrays for this
      entry.total_width=0;
    }
    else
    {
      mp_integer total=array_size*sub_width;
      if(total>(1<<30)) // realistic limit
        throw "array too large for flattening";

      entry.total_width=integer2unsigned(total);
    }
  }
  else if(type_id==ID_vector)
  {
    const vector_typet &vector_type=to_vector_type(type);
    std::size_t sub_width=operator()(vector_type.subtype());

    mp_integer vector_size;

    if(to_integer(vector_type.size(), vector_size))
    {
      // we can still use the theory of arrays for this
      entry.total_width=0;
    }
    else
    {
      mp_integer total=vector_size*sub_width;
      if(total>(1<<30)) // realistic limit
        throw "vector too large for flattening";

      entry.total_width=integer2unsigned(vector_size*sub_width);
    }
  }
  else if(type_id==ID_complex)
  {
    std::size_t sub_width=operator()(type.subtype());
    entry.total_width=integer2unsigned(2*sub_width);
  }
  else if(type_id==ID_code)
  {
  }
  else if(type_id==ID_enum)
  {
    // get number of necessary bits

    std::size_t size=type.find(ID_elements).get_sub().size();
    entry.total_width=integer2unsigned(address_bits(size));
    assert(entry.total_width!=0);
  }
  else if(type_id==ID_c_enum)
  {
    // these have a subtype
    entry.total_width=type.subtype().get_unsigned_int(ID_width);
    assert(entry.total_width!=0);
  }
  else if(type_id==ID_incomplete_c_enum)
  {
    // no width
  }
  else if(type_id==ID_pointer ||
          type_id==ID_reference)
  {
    entry.total_width=config.ansi_c.pointer_width;
  }
  else if(type_id==ID_symbol)
    entry=get_entry(ns.follow(type));
  else if(type_id==ID_struct_tag)
    entry=get_entry(ns.follow_tag(to_struct_tag_type(type)));
  else if(type_id==ID_union_tag)
    entry=get_entry(ns.follow_tag(to_union_tag_type(type)));
  else if(type_id==ID_c_enum_tag)
    entry=get_entry(ns.follow_tag(to_c_enum_tag_type(type)));
  else if(type_id==ID_c_bit_field)
  {
    entry.total_width=to_c_bit_field_type(type).get_width();
  }
  
  return entry;
}
Example #12
0
void c_typecheck_baset::do_designated_initializer(
  exprt &result,
  designatort &designator,
  const exprt &value,
  bool force_constant)
{
  assert(!designator.empty());
  
  if(value.id()==ID_designated_initializer)
  {
    assert(value.operands().size()==1);

    designator=    
      make_designator(
        designator.front().type,
        static_cast<const exprt &>(value.find(ID_designator)));
        
    assert(!designator.empty());
  
    return do_designated_initializer(
      result, designator, value.op0(), force_constant);
  }
  
  exprt *dest=&result;

  // first phase: follow given designator

  for(unsigned i=0; i<designator.size(); i++)
  {
    unsigned index=designator[i].index;
    const typet &type=designator[i].type;
    
    assert(type.id()!=ID_symbol);

    if(type.id()==ID_array ||
       type.id()==ID_struct ||
       type.id()==ID_incomplete_array)
    {
      if(index>=dest->operands().size())
      {
        if(type.id()==ID_incomplete_array)
        {
          exprt zero=zero_initializer(type.subtype(), value.location());
          dest->operands().resize(integer2long(index)+1, zero);
        }
        else
        {
          err_location(value);
          str << "index designator " << index
              << " out of bounds (" << dest->operands().size() << ")";
          throw 0;
        }
      }

      dest=&(dest->operands()[integer2long(index)]);
    }
    else if(type.id()==ID_union)
    {
      // union initialization is quite special
      const union_typet &union_type=to_union_type(type);
      const union_typet::componentt &component=union_type.components()[index];

      // build a union expression from the argument
      exprt union_expr(ID_union, type);
      union_expr.operands().resize(1);
      union_expr.op0()=zero_initializer(component.type(), value.location());
      union_expr.location()=value.location();
      union_expr.set(ID_component_name, component.get_name());

      *dest=union_expr;
      dest=&(dest->op0());
    }
    else
      assert(false);
  }
  
  // second phase: assign value
  // for this, we may need to go down, adding to the designator
  
  while(true)
  {
    // see what type we have to initialize

    typet type=follow(designator.back().subtype);
    assert(type.id()!=ID_symbol);

    // do we initialize a scalar?
    if(type.id()!=ID_struct &&
       type.id()!=ID_union &&
       type.id()!=ID_array &&
       type.id()!=ID_incomplete_array)
    {
      // The initializer for a scalar shall be a single expression,
      // * optionally enclosed in braces. *
      
      if(value.id()==ID_initializer_list &&
         value.operands().size()==1)
        *dest=do_initializer_rec(value.op0(), type, force_constant);
      else
        *dest=do_initializer_rec(value, type, force_constant);

      assert(type==follow(dest->type()));
      
      return; // done
    }

    // see what initializer we are given
    if(value.id()==ID_initializer_list)
    {
      *dest=do_initializer_rec(value, type, force_constant);
      return; // done
    }
    else if(value.id()==ID_string_constant)
    {
      // We stop for initializers that are string-constants,
      // which are like arrays. We only do so if we are to
      // initialize an array of scalars.
      if((type.id()==ID_array || type.id()==ID_incomplete_array) &&
         (follow(type.subtype()).id()==ID_signedbv ||
          follow(type.subtype()).id()==ID_unsignedbv))
      {
        *dest=do_initializer_rec(value, type, force_constant);
        return; // done
      }
    }
    else if(follow(value.type())==type)
    {
      // a struct/union can be initialized directly with
      // an expression of the right type. This doesn't
      // work with arrays, unfortunately.
      if(type.id()==ID_struct || type.id()==ID_union)
      {
        *dest=value;
        return; // done
      }
    }
    
    // we are initializing a compound type, and enter it!
    designator_enter(type, designator);
    
    assert(!dest->operands().empty());
    dest=&(dest->op0());

    // we run into another loop iteration
  }
}
Example #13
0
exprt c_typecheck_baset::zero_initializer(
  const typet &type,
  const locationt &location)
{
  const irep_idt &type_id=type.id();
  
  if(type_id==ID_bool)
  {
    exprt result=false_exprt();
    result.location()=location;
    return result;
  }
  else if(type_id==ID_unsignedbv ||
          type_id==ID_signedbv ||
          type_id==ID_floatbv ||
          type_id==ID_fixedbv ||
          type_id==ID_pointer)
  {
    exprt result=gen_zero(type);
    result.location()=location;
    return result;
  }
  else if(type_id==ID_code)
  {
    err_location(location);
    throw "cannot zero-initialize code-type";
  }
  else if(type_id==ID_c_enum ||
          type_id==ID_incomplete_c_enum)
  {
    constant_exprt value(type);
    value.set_value(ID_0);
    value.location()=location;
    return value;
  }
  else if(type_id==ID_array)
  {
    const array_typet &array_type=to_array_type(type);
    exprt tmpval=zero_initializer(array_type.subtype(), location);

    mp_integer array_size;

    if(array_type.size().id()==ID_infinity)
    {
      exprt value(ID_array_of, type);
      value.copy_to_operands(tmpval);
      value.location()=location;
      return value;
    }
    else if(to_integer(array_type.size(), array_size))
    {
      err_location(location);
      str << "failed to zero-initialize array of non-fixed size `"
          << to_string(array_type.size()) << "'";
      throw 0;
    }
      
    if(array_size<0)
    {
      err_location(location);
      throw "failed to zero-initialize array of with negative size";
    }

    exprt value(ID_array, type);
    value.operands().resize(integer2long(array_size), tmpval);
    value.location()=location;

    return value;
  }
  else if(type_id==ID_incomplete_array)
  {
    // we initialize this with an empty array

    exprt value(ID_array, type);
    value.type().id(ID_array);
    value.type().set(ID_size, gen_zero(size_type()));
    value.location()=location;

    return value;
  }
  else if(type_id==ID_struct)
  {
    const struct_typet::componentst &components=
      to_struct_type(type).components();

    exprt value(ID_struct, type);
    
    value.operands().reserve(components.size());

    for(struct_typet::componentst::const_iterator
        it=components.begin();
        it!=components.end();
        it++)
      value.copy_to_operands(zero_initializer(it->type(), location));

    value.location()=location;

    return value;
  }
  else if(type_id==ID_union)
  {
    const union_typet::componentst &components=
      to_union_type(type).components();

    exprt value(ID_union, type);

    if(components.empty())
      return value; // stupid empty union

    value.set(ID_component_name, components.front().get(ID_name));
    value.copy_to_operands(
      zero_initializer(components.front().type(), location));
    value.location()=location;

    return value;
  }
  else if(type_id==ID_symbol)
    return zero_initializer(follow(type), location);
  else
  {
    err_location(location);
    str << "Failed to zero-initialize `" << to_string(type)
        << "'";
    throw 0;
  }
}
void c_typecheck_baset::designator_enter(
  const typet &type,
  designatort &designator)
{
  designatort::entryt entry;
  entry.type=type;
  entry.index=0;

  const typet &full_type=follow(type);

  if(full_type.id()==ID_struct)
  {
    const struct_typet &struct_type=to_struct_type(full_type);

    entry.size=struct_type.components().size();
    entry.subtype.make_nil();

    for(struct_typet::componentst::const_iterator
        it=struct_type.components().begin();
        it!=struct_type.components().end();
        ++it)
    {
      if(it->type().id()!=ID_code &&
         !it->get_is_padding())
      {
        entry.subtype=it->type();
        break;
      }

      ++entry.index;
    }
  }
  else if(full_type.id()==ID_union)
  {
    const union_typet &union_type=to_union_type(full_type);

    if(union_type.components().empty())
    {
      entry.size=0;
      entry.subtype.make_nil();
    }
    else
    {
      // The default is to unitialize using the first member of the
      // union.
      entry.size=1;
      entry.subtype=union_type.components().front().type();
    }
  }
  else if(full_type.id()==ID_array)
  {
    const array_typet &array_type=to_array_type(full_type);

    if(array_type.size().is_nil())
    {
      entry.size=0;
      entry.subtype=array_type.subtype();
    }
    else
    {
      mp_integer array_size;

      if(to_integer(array_type.size(), array_size))
      {
        err_location(array_type.size());
        error() << "array has non-constant size `"
                << to_string(array_type.size()) << "'" << eom;
        throw 0;
      }

      entry.size=integer2size_t(array_size);
      entry.subtype=array_type.subtype();
    }
  }
  else if(full_type.id()==ID_vector)
  {
    const vector_typet &vector_type=to_vector_type(full_type);

    mp_integer vector_size;

    if(to_integer(vector_type.size(), vector_size))
    {
      err_location(vector_type.size());
      error() << "vector has non-constant size `"
              << to_string(vector_type.size()) << "'" << eom;
      throw 0;
    }

    entry.size=integer2size_t(vector_size);
    entry.subtype=vector_type.subtype();
  }
  else
    assert(false);

  designator.push_entry(entry);
}
Example #15
0
void c_typecheck_baset::typecheck_compound_body(
  struct_union_typet &type)
{
  struct_union_typet::componentst &components=type.components();

  struct_union_typet::componentst old_components;
  old_components.swap(components);

  // We get these as declarations!
  for(auto &decl : old_components)
  {
    // the arguments are member declarations or static assertions
    assert(decl.id()==ID_declaration);

    ansi_c_declarationt &declaration=
      to_ansi_c_declaration(static_cast<exprt &>(decl));

    if(declaration.get_is_static_assert())
    {
      struct_union_typet::componentt new_component;
      new_component.id(ID_static_assert);
      new_component.add_source_location()=declaration.source_location();
      new_component.operands().swap(declaration.operands());
      assert(new_component.operands().size()==2);
      components.push_back(new_component);
    }
    else
    {
      // do first half of type
      typecheck_type(declaration.type());
      make_already_typechecked(declaration.type());

      for(const auto &declarator : declaration.declarators())
      {
        struct_union_typet::componentt new_component;

        new_component.add_source_location()=
          declarator.source_location();
        new_component.set(ID_name, declarator.get_base_name());
        new_component.set(ID_pretty_name, declarator.get_base_name());
        new_component.type()=declaration.full_type(declarator);

        typecheck_type(new_component.type());

        if(!is_complete_type(new_component.type()) &&
           (new_component.type().id()!=ID_array ||
            !to_array_type(new_component.type()).is_incomplete()))
        {
          error().source_location=new_component.type().source_location();
          error() << "incomplete type not permitted here" << eom;
          throw 0;
        }

        components.push_back(new_component);
      }
    }
  }

  unsigned anon_member_counter=0;

  // scan for anonymous members, and name them
  for(auto &member : components)
  {
    if(member.get_name()!=irep_idt())
      continue;

    member.set_name("$anon"+std::to_string(anon_member_counter++));
    member.set_anonymous(true);
  }

  // scan for duplicate members

  {
    std::unordered_set<irep_idt, irep_id_hash> members;

    for(struct_union_typet::componentst::iterator
        it=components.begin();
        it!=components.end();
        it++)
    {
      if(!members.insert(it->get_name()).second)
      {
        error().source_location=it->source_location();
        error() << "duplicate member '" << it->get_name() << '\'' << eom;
        throw 0;
      }
    }
  }

  // We allow an incomplete (C99) array as _last_ member!
  // Zero-length is allowed everywhere.

  if(type.id()==ID_struct ||
     type.id()==ID_union)
  {
    for(struct_union_typet::componentst::iterator
        it=components.begin();
        it!=components.end();
        it++)
    {
      typet &c_type=it->type();

      if(c_type.id()==ID_array &&
         to_array_type(c_type).is_incomplete())
      {
        // needs to be last member
        if(type.id()==ID_struct && it!=--components.end())
        {
          error().source_location=it->source_location();
          error() << "flexible struct member must be last member" << eom;
          throw 0;
        }

        // make it zero-length
        c_type.id(ID_array);
        c_type.set(ID_size, from_integer(0, index_type()));
      }
    }
  }

  // We may add some minimal padding inside and at
  // the end of structs and
  // as additional member for unions.

  if(type.id()==ID_struct)
    add_padding(to_struct_type(type), *this);
  else if(type.id()==ID_union)
    add_padding(to_union_type(type), *this);

  // Now remove zero-width bit-fields, these are just
  // for adjusting alignment.
  for(struct_typet::componentst::iterator
      it=components.begin();
      it!=components.end();
      ) // blank
  {
    if(it->type().id()==ID_c_bit_field &&
       to_c_bit_field_type(it->type()).get_width()==0)
      it=components.erase(it);
    else
      it++;
  }

  // finally, check _Static_assert inside the compound
  for(struct_union_typet::componentst::iterator
      it=components.begin();
      it!=components.end();
      ) // no it++
  {
    if(it->id()==ID_static_assert)
    {
      assert(it->operands().size()==2);
      exprt &assertion=it->op0();
      typecheck_expr(assertion);
      typecheck_expr(it->op1());
      assertion.make_typecast(bool_typet());
      make_constant(assertion);

      if(assertion.is_false())
      {
        error().source_location=it->source_location();
        error() << "failed _Static_assert" << eom;
        throw 0;
      }
      else if(!assertion.is_true())
      {
        // should warn/complain
      }

      it=components.erase(it);
    }
    else
      it++;
  }
}
void c_typecheck_baset::do_designated_initializer(
  exprt &result,
  designatort &designator,
  const exprt &value,
  bool force_constant)
{
  assert(!designator.empty());

  if(value.id()==ID_designated_initializer)
  {
    assert(value.operands().size()==1);

    designator=
      make_designator(
        designator.front().type,
        static_cast<const exprt &>(value.find(ID_designator)));

    assert(!designator.empty());

    return do_designated_initializer(
      result, designator, value.op0(), force_constant);
  }

  exprt *dest=&result;

  // first phase: follow given designator

  for(size_t i=0; i<designator.size(); i++)
  {
    size_t index=designator[i].index;
    const typet &type=designator[i].type;
    const typet &full_type=follow(type);

    if(full_type.id()==ID_array ||
       full_type.id()==ID_vector)
    {
      if(index>=dest->operands().size())
      {
        if(full_type.id()==ID_array &&
           (to_array_type(full_type).size().is_zero() ||
            to_array_type(full_type).size().is_nil()))
        {
          // we are willing to grow an incomplete or zero-sized array
          exprt zero=
            zero_initializer(
              full_type.subtype(),
              value.source_location(),
              *this,
              get_message_handler());
          dest->operands().resize(integer2size_t(index)+1, zero);

          // todo: adjust type!
        }
        else
        {
          err_location(value);
          error() << "array index designator " << index
                  << " out of bounds (" << dest->operands().size()
                  << ")" << eom;
          throw 0;
        }
      }

      dest=&(dest->operands()[integer2size_t(index)]);
    }
    else if(full_type.id()==ID_struct)
    {
      const struct_typet::componentst &components=
        to_struct_type(full_type).components();

      if(index>=dest->operands().size())
      {
        err_location(value);
        error() << "structure member designator " << index
                << " out of bounds (" << dest->operands().size()
                << ")" << eom;
        throw 0;
      }

      assert(index<components.size());
      assert(components[index].type().id()!=ID_code &&
             !components[index].get_is_padding());

      dest=&(dest->operands()[index]);
    }
    else if(full_type.id()==ID_union)
    {
      const union_typet &union_type=to_union_type(full_type);

      const union_typet::componentst &components=
        union_type.components();

      assert(index<components.size());

      const union_typet::componentt &component=union_type.components()[index];

      if(dest->id()==ID_union &&
         dest->get(ID_component_name)==component.get_name())
      {
        // Already right union component. We can initialize multiple submembers,
        // so do not overwrite this.
      }
      else
      {
        // Note that gcc issues a warning if the union component is switched.
        // Build a union expression from given component.
        union_exprt union_expr(type);
        union_expr.op()=
          zero_initializer(
            component.type(),
            value.source_location(),
            *this,
            get_message_handler());
        union_expr.add_source_location()=value.source_location();
        union_expr.set_component_name(component.get_name());
        *dest=union_expr;
      }

      dest=&(dest->op0());
    }
    else
      assert(false);
  }

  // second phase: assign value
  // for this, we may need to go down, adding to the designator

  while(true)
  {
    // see what type we have to initialize

    const typet &type=designator.back().subtype;
    const typet &full_type=follow(type);
    assert(full_type.id()!=ID_symbol);

    // do we initialize a scalar?
    if(full_type.id()!=ID_struct &&
       full_type.id()!=ID_union &&
       full_type.id()!=ID_array &&
       full_type.id()!=ID_vector)
    {
      // The initializer for a scalar shall be a single expression,
      // * optionally enclosed in braces. *

      if(value.id()==ID_initializer_list &&
         value.operands().size()==1)
        *dest=do_initializer_rec(value.op0(), type, force_constant);
      else
        *dest=do_initializer_rec(value, type, force_constant);

      assert(full_type==follow(dest->type()));

      return; // done
    }

    // union? The component in the zero initializer might
    // not be the first one.
    if(full_type.id()==ID_union)
    {
      const union_typet &union_type=to_union_type(full_type);

      const union_typet::componentst &components=
        union_type.components();

      if(!components.empty())
      {
        const union_typet::componentt &component=
          union_type.components().front();

        union_exprt union_expr(type);
        union_expr.op()=
          zero_initializer(
            component.type(),
            value.source_location(),
            *this,
            get_message_handler());
        union_expr.add_source_location()=value.source_location();
        union_expr.set_component_name(component.get_name());
        *dest=union_expr;
      }
    }

    // see what initializer we are given
    if(value.id()==ID_initializer_list)
    {
      *dest=do_initializer_rec(value, type, force_constant);
      return; // done
    }
    else if(value.id()==ID_string_constant)
    {
      // We stop for initializers that are string-constants,
      // which are like arrays. We only do so if we are to
      // initialize an array of scalars.
      if(full_type.id()==ID_array &&
         (follow(full_type.subtype()).id()==ID_signedbv ||
          follow(full_type.subtype()).id()==ID_unsignedbv))
      {
        *dest=do_initializer_rec(value, type, force_constant);
        return; // done
      }
    }
    else if(follow(value.type())==full_type)
    {
      // a struct/union/vector can be initialized directly with
      // an expression of the right type. This doesn't
      // work with arrays, unfortunately.
      if(full_type.id()==ID_struct ||
         full_type.id()==ID_union ||
         full_type.id()==ID_vector)
      {
        *dest=value;
        return; // done
      }
    }

    assert(full_type.id()==ID_struct ||
           full_type.id()==ID_union ||
           full_type.id()==ID_array ||
           full_type.id()==ID_vector);

    // we are initializing a compound type, and enter it!
    // this may change the type, full_type might not be valid anymore
    const typet dest_type=full_type;
    designator_enter(type, designator);

    if(dest->operands().empty())
    {
      err_location(value);
      error() << "cannot initialize type `"
              << to_string(dest_type) << "' using value `"
              << to_string(value) << "'" << eom;
      throw 0;
    }

    dest=&(dest->op0());

    // we run into another loop iteration
  }
}
Example #17
0
json_objectt json(
  const typet &type,
  const namespacet &ns)
{
  if(type.id()==ID_symbol)
    return json(ns.follow(type), ns);

  json_objectt result;

  if(type.id()==ID_unsignedbv)
  {
    result["name"]=json_stringt("integer");
    result["width"]=
      json_numbert(i2string(to_unsignedbv_type(type).get_width()));
  }
  else if(type.id()==ID_signedbv)
  {
    result["name"]=json_stringt("integer");
    result["width"]=json_numbert(i2string(to_signedbv_type(type).get_width()));
  }
  else if(type.id()==ID_floatbv)
  {
    result["name"]=json_stringt("float");
    result["width"]=json_numbert(i2string(to_floatbv_type(type).get_width()));
  }
  else if(type.id()==ID_bv)
  {
    result["name"]=json_stringt("integer");
    result["width"]=json_numbert(i2string(to_bv_type(type).get_width()));
  }
  else if(type.id()==ID_c_bit_field)
  {
    result["name"]=json_stringt("integer");
    result["width"]=
      json_numbert(i2string(to_c_bit_field_type(type).get_width()));
  }
  else if(type.id()==ID_c_enum_tag)
  {
    // we return the base type
    return json(ns.follow_tag(to_c_enum_tag_type(type)).subtype(), ns);
  }
  else if(type.id()==ID_fixedbv)
  {
    result["name"]=json_stringt("fixed");
    result["width"]=json_numbert(i2string(to_fixedbv_type(type).get_width()));
  }
  else if(type.id()==ID_pointer)
  {
    result["name"]=json_stringt("pointer");
    result["subtype"]=json(type.subtype(), ns);
  }
  else if(type.id()==ID_bool)
  {
    result["name"]=json_stringt("boolean");
  }
  else if(type.id()==ID_array)
  {
    result["name"]=json_stringt("array");
    result["subtype"]=json(type.subtype(), ns);
  }
  else if(type.id()==ID_vector)
  {
    result["name"]=json_stringt("vector");
    result["subtype"]=json(type.subtype(), ns);
    result["size"]=json(to_vector_type(type).size(), ns);
  }
  else if(type.id()==ID_struct)
  {
    result["name"]=json_stringt("struct");
    json_arrayt &members=result["members"].make_array();
    const struct_typet::componentst &components=
      to_struct_type(type).components();
    for(const auto & it : components)
    {
      json_objectt &e=members.push_back().make_object();
      e["name"]=json_stringt(id2string(it.get_name()));
      e["type"]=json(it.type(), ns);
    }
  }
  else if(type.id()==ID_union)
  {
    result["name"]=json_stringt("union");
    json_arrayt &members=result["members"].make_array();
    const union_typet::componentst &components=
      to_union_type(type).components();
    for(const auto & it : components)
    {
      json_objectt &e=members.push_back().make_object();
      e["name"]=json_stringt(id2string(it.get_name()));
      e["type"]=json(it.type(), ns);
    }
  }
  else
    result["name"]=json_stringt("unknown");

  return result;
}