Example #1
0
bool full_eq(const irept &i1, const irept &i2)
{
#ifdef SHARING
    if(i1.data==i2.data) return true;
#endif

    if(i1.id()!=i2.id()) return false;

    const irept::subt &i1_sub=i1.get_sub();
    const irept::subt &i2_sub=i2.get_sub();
    const irept::named_subt &i1_named_sub=i1.get_named_sub();
    const irept::named_subt &i2_named_sub=i2.get_named_sub();
    const irept::named_subt &i1_comments=i1.get_comments();
    const irept::named_subt &i2_comments=i2.get_comments();

    if(i1_sub.size()      !=i2_sub.size()) return false;
    if(i1_named_sub.size()!=i2_named_sub.size()) return false;
    if(i1_comments.size() !=i2_comments.size()) return false;

    for(unsigned i=0; i<i1_sub.size(); i++)
        if(!full_eq(i1_sub[i], i2_sub[i]))
            return false;

    {
        irept::named_subt::const_iterator i1_it=i1_named_sub.begin();
        irept::named_subt::const_iterator i2_it=i2_named_sub.begin();

        for(; i1_it!=i1_named_sub.end(); i1_it++, i2_it++)
            if(i1_it->first!=i2_it->first ||
                    !full_eq(i1_it->second, i2_it->second))
                return false;
    }

    {
        irept::named_subt::const_iterator i1_it=i1_comments.begin();
        irept::named_subt::const_iterator i2_it=i2_comments.begin();

        for(; i1_it!=i1_comments.end(); i1_it++, i2_it++)
            if(i1_it->first!=i2_it->first ||
                    !full_eq(i1_it->second, i2_it->second))
                return false;
    }

    return true;
}
Example #2
0
void c_typecastt::implicit_typecast_followed(
  exprt &expr,
  const typet &src_type,
  const typet &orig_dest_type,
  const typet &dest_type)
{
  // 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.

    // GCC docs say:
    //  If the union member type is a pointer, qualifiers like const on the
    //  referenced type must be respected, just as with normal pointer
    //  conversions.
    // But it is accepted, and Clang doesn't even emit a warning (GCC 4.7 does)
    typet src_type_no_const=src_type;
    if(src_type.id()==ID_pointer &&
       src_type.subtype().get_bool(ID_C_constant))
      src_type_no_const.subtype().remove(ID_C_constant);
    
    // 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_no_const, it->type()))
      {
        // build union constructor
        exprt union_expr(ID_union, orig_dest_type);
        union_expr.move_to_operands(expr);
        if(!full_eq(src_type, src_type_no_const))
          do_typecast(union_expr.op0(), src_type_no_const);
        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(simplify_expr(expr, ns).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, orig_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_sub, dest_sub, ns))
      {
        // ok
      }
      else if((is_number(src_sub) || src_sub.id()==ID_c_enum || src_sub.id()==ID_c_enum_tag) &&
              (is_number(dest_sub) || dest_sub.id()==ID_c_enum || src_sub.id()==ID_c_enum_tag))
      {
        // 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, orig_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, orig_dest_type);
}