Beispiel #1
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());
}
Beispiel #2
0
void base_type_rec(
  typet &type, const namespacet &ns, std::set<irep_idt> &symb)
{
  if(type.id()==ID_symbol ||
     type.id()==ID_c_enum_tag ||
     type.id()==ID_struct_tag ||
     type.id()==ID_union_tag)
  {
    const symbolt *symbol;

    if(!ns.lookup(type.get(ID_identifier), symbol) &&
       symbol->is_type &&
       !symbol->type.is_nil())
    {
      type=symbol->type;
      base_type_rec(type, ns, symb); // recursive call
      return;
    }
  }
  else if(type.id()==ID_array)
  {
    base_type_rec(to_array_type(type).subtype(), ns, symb);
  }
  else if(type.id()==ID_struct ||
          type.id()==ID_union)
  {
    struct_union_typet::componentst &components=
      to_struct_union_type(type).components();

    for(auto &component : components)
      base_type_rec(component.type(), ns, symb);
  }
  else if(type.id()==ID_pointer)
  {
    typet &subtype=to_pointer_type(type).subtype();

    // we need to avoid running into an infinite loop
    if(subtype.id()==ID_symbol ||
       subtype.id()==ID_c_enum_tag ||
       subtype.id()==ID_struct_tag ||
       subtype.id()==ID_union_tag)
    {
      const irep_idt &id=subtype.get(ID_identifier);

      if(symb.find(id)!=symb.end())
        return;

      symb.insert(id);

      base_type_rec(subtype, ns, symb);

      symb.erase(id);
    }
    else
      base_type_rec(subtype, ns, symb);
  }
}
Beispiel #3
0
bool dereferencet::type_compatible(
  const typet &object_type,
  const typet &dereference_type) const
{
  if(dereference_type.id()==ID_empty)
    return true; // always ok

  if(base_type_eq(object_type, dereference_type, ns))
    return true; // ok, they just match

  // check for struct prefixes

  if(object_type.id()==ID_struct &&
     dereference_type.id()==ID_struct)
  {
    if(to_struct_type(dereference_type).is_prefix_of(
         to_struct_type(object_type)))
      return true; // ok, dreference_type is a prefix of object_type
  }

  // any code is ok
  if(dereference_type.id()==ID_code &&
     object_type.id()==ID_code)
    return true;

  // bit vectors of same size are ok
  if((object_type.id()==ID_signedbv || object_type.id()==ID_unsignedbv) &&
     (dereference_type.id()==ID_signedbv ||
      dereference_type.id()==ID_unsignedbv))
  {
    return object_type.get(ID_width)==dereference_type.get(ID_width);
  }

  // Any pointer to pointer is always ok,
  // but should likely check that width is the same.
  if(object_type.id()==ID_pointer &&
     dereference_type.id()==ID_pointer)
    return true;

  // really different

  return false;
}
void bv_spect::from_type(const typet &type)
{
  if(type.id()==ID_unsignedbv)
    is_signed=false;
  else if(type.id()==ID_signedbv)
    is_signed=true;
  else
    assert(0);
  
  width=atoi(type.get(ID_width).c_str());
}
Beispiel #5
0
static std::string type2name_symbol(
  const typet &type,
  const namespacet &ns,
  symbol_numbert &symbol_number)
{
  const irep_idt &identifier=type.get(ID_identifier);

  const symbolt *symbol;

  if(ns.lookup(identifier, symbol))
    return "SYM#"+id2string(identifier)+"#";

  assert(symbol && symbol->is_type);

  if(symbol->type.id()!=ID_struct &&
     symbol->type.id()!=ID_union)
    return type2name(symbol->type, ns, symbol_number);

  std::string result;

  // assign each symbol a number when seen for the first time
  std::pair<symbol_numbert::iterator, bool> entry=
    symbol_number.insert(std::make_pair(
        identifier,
        std::make_pair(symbol_number.size(), true)));

  // new entry, add definition
  if(entry.second)
  {
    result="SYM#"+std::to_string(entry.first->second.first);
    result+="={";
    result+=type2name(symbol->type, ns, symbol_number);
    result+='}';

    entry.first->second.second=false;
  }
#if 0
  // in recursion, print the shorthand only
  else if(entry.first->second.second)
    result="SYM#"+std::to_string(entry.first->second.first);
  // entering recursion
  else
  {
    entry.first->second.second=true;
    result=type2name(symbol->type, ns, symbol_number);
    entry.first->second.second=false;
  }
#else
  // shorthand only as structs/unions are always symbols
  else
Beispiel #6
0
void c_typecastt::do_typecast(exprt &expr, const typet &type)
{
  // special case: array -> pointer is actually
  // something like address_of
  
  const typet &expr_type=ns.follow(expr.type());

  if(expr_type.id()==ID_array)
  {
    index_exprt index;
    index.array()=expr;
    index.index()=gen_zero(index_type());
    index.type()=expr_type.subtype();
    expr=address_of_exprt(index);
    if(ns.follow(expr.type())!=ns.follow(type))
      expr.make_typecast(type);
    return;
  }

  if(expr_type!=type)
  {
    // C booleans are special: we compile to ?0:1
    
    if(type.get(ID_C_c_type)==ID_bool)
    {
      if(expr_type.id()==ID_bool) // bool -> _Bool
      {
        exprt result=if_exprt(expr, gen_one(type), gen_zero(type));
        expr.swap(result);
      }
      else // * -> _Bool
      {
        equal_exprt equal_zero(expr, gen_zero(expr_type));
        exprt result=if_exprt(equal_zero, gen_zero(type), gen_one(type));
        expr.swap(result);
      }
    }
    else
    {    
      expr.make_typecast(type);
    }
  }
}
Beispiel #7
0
void c_typecastt::do_typecast(exprt &expr, const typet &dest_type)
{
  // special case: array -> pointer is actually
  // something like address_of
  
  const typet &src_type=ns.follow(expr.type());

  if(src_type.id()==ID_array)
  {
    index_exprt index;
    index.array()=expr;
    index.index()=gen_zero(index_type());
    index.type()=src_type.subtype();
    expr=address_of_exprt(index);
    if(ns.follow(expr.type())!=ns.follow(dest_type))
      expr.make_typecast(dest_type);
    return;
  }

  if(src_type!=dest_type)
  {
    // C booleans are special; we produce the
    // explicit comparision with zero.
    // Note that this requires ieee_float_notequal
    // in case of floating-point numbers.
    
    if(dest_type.get(ID_C_c_type)==ID_bool)
    {
      expr=is_not_zero(expr, ns);
      expr.make_typecast(dest_type);
    }
    else if(dest_type.id()==ID_bool)
    {
      expr=is_not_zero(expr, ns);
    }
    else
    {    
      expr.make_typecast(dest_type);
    }
  }
}
Beispiel #8
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 #9
0
c_typecastt::c_typet c_typecastt::get_c_type(
  const typet &type)
{
  unsigned width=type.get_int(ID_width);
  
  if(type.id()==ID_signedbv)
  {
    if(width<=config.ansi_c.char_width)
      return CHAR;
    else if(width<=config.ansi_c.short_int_width)
      return SHORT;
    else if(width<=config.ansi_c.int_width)
      return INT;
    else if(width<=config.ansi_c.long_int_width)
      return LONG;
    else if(width<=config.ansi_c.long_long_int_width)
      return LONGLONG;
    else
      return LARGE_SIGNED_INT;
  }
  else if(type.id()==ID_unsignedbv)
  {
    if(type.get(ID_C_c_type)==ID_bool)
      return BOOL;
  
    if(width<=config.ansi_c.char_width)
      return UCHAR;
    else if(width<=config.ansi_c.short_int_width)
      return USHORT;
    else if(width<=config.ansi_c.int_width)
      return UINT;
    else if(width<=config.ansi_c.long_int_width)
      return ULONG;
    else if(width<=config.ansi_c.long_long_int_width)
      return ULONGLONG;
    else
      return LARGE_UNSIGNED_INT;
  }
  else if(type.id()==ID_bool)
    return BOOL;
  else if(type.id()==ID_floatbv ||
          type.id()==ID_fixedbv)
  {
    if(width<=config.ansi_c.single_width)
      return SINGLE;
    else if(width<=config.ansi_c.double_width)
      return DOUBLE;
    else if(width<=config.ansi_c.long_double_width)
      return LONGDOUBLE;
  }
  else if(type.id()==ID_pointer)
  {
    if(type.subtype().id()==ID_empty)
      return VOIDPTR;
    else
      return PTR;
  }
  else if(type.id()==ID_array)
  {
    return PTR;
  }
  else if(type.id()==ID_c_enum ||
          type.id()==ID_incomplete_c_enum)
  {
    return INT;
  }
  else if(type.id()==ID_symbol)
    return get_c_type(ns.follow(type));
  else if(type.id()==ID_rational)
    return RATIONAL;
  else if(type.id()==ID_real)
    return REAL;
  else if(type.id()==ID_complex)
    return COMPLEX;
    
  return OTHER;  
}
Beispiel #10
0
void c_typecheck_baset::typecheck_type(typet &type)
{
  // we first convert, and then check
  {
    ansi_c_convert_typet ansi_c_convert_type(get_message_handler());

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

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

    type=type.subtype();

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

    return; // done
  }

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

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

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

    typet underlying_type=type.subtype();

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

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

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

      typet result;

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

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

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

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

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

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

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

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

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

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

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

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

  // do a mild bit of rule checking

  if(type.get_bool(ID_C_restricted) &&
     type.id()!=ID_pointer &&
     type.id()!=ID_array)
  {
    error().source_location=type.source_location();
    error() << "only a pointer can be 'restrict'" << eom;
    throw 0;
  }
}
unsigned bv_width(const typet &type)
{
  return atoi(type.get(ID_width).c_str());
}
Beispiel #12
0
bool base_type_eqt::base_type_eq_rec(
  const typet &type1,
  const typet &type2)
{
  if(type1==type2)
    return true;

  #if 0
  std::cout << "T1: " << type1.pretty() << std::endl;
  std::cout << "T2: " << type2.pretty() << std::endl;
  #endif

  // loop avoidance
  if((type1.id()==ID_symbol ||
      type1.id()==ID_c_enum_tag ||
      type1.id()==ID_struct_tag ||
      type1.id()==ID_union_tag) &&
     type2.id()==type1.id())
  {
    // already in same set?
    if(identifiers.make_union(
         type1.get(ID_identifier),
         type2.get(ID_identifier)))
      return true;
  }

  if(type1.id()==ID_symbol ||
     type1.id()==ID_c_enum_tag ||
     type1.id()==ID_struct_tag ||
     type1.id()==ID_union_tag)
  {
    const symbolt &symbol=
      ns.lookup(type1.get(ID_identifier));

    if(!symbol.is_type)
      return false;

    return base_type_eq_rec(symbol.type, type2);
  }

  if(type2.id()==ID_symbol ||
     type2.id()==ID_c_enum_tag ||
     type2.id()==ID_struct_tag ||
     type2.id()==ID_union_tag)
  {
    const symbolt &symbol=
      ns.lookup(type2.get(ID_identifier));

    if(!symbol.is_type)
      return false;

    return base_type_eq_rec(type1, symbol.type);
  }

  if(type1.id()!=type2.id())
    return false;

  if(type1.id()==ID_struct ||
     type1.id()==ID_union)
  {
    const struct_union_typet::componentst &components1=
      to_struct_union_type(type1).components();

    const struct_union_typet::componentst &components2=
      to_struct_union_type(type2).components();

    if(components1.size()!=components2.size())
      return false;

    for(unsigned i=0; i<components1.size(); i++)
    {
      const typet &subtype1=components1[i].type();
      const typet &subtype2=components2[i].type();
      if(!base_type_eq_rec(subtype1, subtype2)) return false;
      if(components1[i].get_name()!=components2[i].get_name()) return false;
    }

    return true;
  }
  else if(type1.id()==ID_incomplete_struct)
  {
    return true;
  }
  else if(type1.id()==ID_incomplete_union)
  {
    return true;
  }
  else if(type1.id()==ID_code)
  {
    const code_typet::parameterst &parameters1=
      to_code_type(type1).parameters();

    const code_typet::parameterst &parameters2=
      to_code_type(type2).parameters();

    if(parameters1.size()!=parameters2.size())
      return false;

    for(unsigned i=0; i<parameters1.size(); i++)
    {
      const typet &subtype1=parameters1[i].type();
      const typet &subtype2=parameters2[i].type();
      if(!base_type_eq_rec(subtype1, subtype2)) return false;
    }

    const typet &return_type1=to_code_type(type1).return_type();
    const typet &return_type2=to_code_type(type2).return_type();

    if(!base_type_eq_rec(return_type1, return_type2))
      return false;

    return true;
  }
  else if(type1.id()==ID_pointer)
  {
    return base_type_eq_rec(
      to_pointer_type(type1).subtype(), to_pointer_type(type2).subtype());
  }
  else if(type1.id()==ID_array)
  {
    if(!base_type_eq_rec(
      to_array_type(type1).subtype(), to_array_type(type2).subtype()))
      return false;

    if(to_array_type(type1).size()!=to_array_type(type2).size())
      return false;

    return true;
  }
  else if(type1.id()==ID_incomplete_array)
  {
    return base_type_eq_rec(
      to_incomplete_array_type(type1).subtype(),
      to_incomplete_array_type(type2).subtype());
  }

  // the below will go away
  typet tmp1(type1), tmp2(type2);

  base_type(tmp1, ns);
  base_type(tmp2, ns);

  return tmp1==tmp2;
}