void c_typecastt::implicit_typecast_arithmetic( exprt &expr, c_typet c_type) { typet new_type; const typet &expr_type=ns.follow(expr.type()); switch(c_type) { case PTR: if(expr_type.id()==ID_array) { new_type.id(ID_pointer); new_type.subtype()=expr_type.subtype(); break; } return; case BOOL: new_type=bool_typet(); break; case CHAR: assert(false); // should always be promoted to int case UCHAR: assert(false); // should always be promoted to int case SHORT: assert(false); // should always be promoted to int case USHORT: assert(false); // should always be promoted to int case INT: new_type=int_type(); break; case UINT: new_type=uint_type(); break; case LONG: new_type=long_int_type(); break; case ULONG: new_type=long_uint_type(); break; case LONGLONG: new_type=long_long_int_type(); break; case ULONGLONG: new_type=long_long_uint_type(); break; case SINGLE: new_type=float_type(); break; case DOUBLE: new_type=double_type(); break; case LONGDOUBLE: new_type=long_double_type(); break; case RATIONAL: new_type=rational_typet(); break; case REAL: new_type=real_typet(); break; case INTEGER: new_type=integer_typet(); break; case COMPLEX: return; // do nothing default: return; } if(new_type!=expr_type) { if(new_type.id()==ID_pointer && expr_type.id()==ID_array) { exprt index_expr(ID_index, expr_type.subtype()); index_expr.reserve_operands(2); index_expr.move_to_operands(expr); index_expr.copy_to_operands(gen_zero(index_type())); expr=exprt(ID_address_of, new_type); expr.move_to_operands(index_expr); } else do_typecast(expr, new_type); } }
// Convert C-string to a Ruby instance of Ruby type "type" VALUE typecast(const char *value, long length, const VALUE type, int encoding) { if (!value) { return Qnil; } if (type == rb_cTrueClass) { return (value == 0 || strcmp("0", value) == 0) ? Qfalse : Qtrue; } else if (type == rb_cByteArray) { return rb_funcall(rb_cByteArray, ID_NEW, 1, rb_str_new(value, length)); } else { return do_typecast(value, length, type, encoding); } }
void c_typecastt::implicit_typecast_arithmetic( exprt &expr, c_typet c_type) { typet new_type; const typet &expr_type=ns.follow(expr.type()); switch(c_type) { case PTR: if(expr_type.id()==ID_array) { new_type.id(ID_pointer); new_type.subtype()=expr_type.subtype(); break; } return; case BOOL: assert(false); // should always be promoted to int case CHAR: assert(false); // should always be promoted to int case UCHAR: assert(false); // should always be promoted to int case SHORT: assert(false); // should always be promoted to int case USHORT: assert(false); // should always be promoted to int case INT: new_type=signed_int_type(); break; case UINT: new_type=unsigned_int_type(); break; case LONG: new_type=signed_long_int_type(); break; case ULONG: new_type=unsigned_long_int_type(); break; case LONGLONG: new_type=signed_long_long_int_type(); break; case ULONGLONG: new_type=unsigned_long_long_int_type(); break; case SINGLE: new_type=float_type(); break; case DOUBLE: new_type=double_type(); break; case LONGDOUBLE: new_type=long_double_type(); break; case FLOAT128: new_type=ieee_float_spect::quadruple_precision().to_type(); break; case RATIONAL: new_type=rational_typet(); break; case REAL: new_type=real_typet(); break; case INTEGER: new_type=integer_typet(); break; case COMPLEX: return; // do nothing default: return; } if(new_type!=expr_type) do_typecast(expr, new_type); }
void c_typecastt::implicit_typecast_arithmetic( exprt &expr1, exprt &expr2) { const typet &type1=ns.follow(expr1.type()); const typet &type2=ns.follow(expr2.type()); c_typet c_type1=get_c_type(type1), c_type2=get_c_type(type2); c_typet max_type=std::max(c_type1, c_type2); // "If an int can represent all values of the original type, the // value is converted to an int; otherwise, it is converted to // an unsigned int." // The second case can arise if we promote any unsigned type // that is as large as unsigned int. if(config.ansi_c.short_int_width==config.ansi_c.int_width && max_type==USHORT) max_type=UINT; else if(config.ansi_c.char_width==config.ansi_c.int_width && max_type==UCHAR) max_type=UINT; else max_type=std::max(max_type, INT); if(max_type==LARGE_SIGNED_INT || max_type==LARGE_UNSIGNED_INT) { // get the biggest width of both unsigned width1=type1.get_int(ID_width); unsigned width2=type2.get_int(ID_width); // produce type typet result_type; if(width1==width2) { if(max_type==LARGE_SIGNED_INT) result_type=signedbv_typet(width1); else result_type=unsignedbv_typet(width1); } else if(width1>width2) result_type=type1; else // width1<width2 result_type=type2; do_typecast(expr1, result_type); do_typecast(expr2, result_type); return; } else if(max_type==COMPLEX) { if(c_type1==COMPLEX && c_type2==COMPLEX) { // promote to the one with bigger subtype if(get_c_type(type1.subtype())>get_c_type(type2.subtype())) do_typecast(expr2, type1); else do_typecast(expr1, type2); } else if(c_type1==COMPLEX) { assert(c_type1==COMPLEX && c_type2!=COMPLEX); do_typecast(expr2, type1.subtype()); do_typecast(expr2, type1); } else { assert(c_type1!=COMPLEX && c_type2==COMPLEX); do_typecast(expr1, type2.subtype()); do_typecast(expr1, type2); } return; } implicit_typecast_arithmetic(expr1, max_type); implicit_typecast_arithmetic(expr2, max_type); if(max_type==PTR) { if(c_type1==VOIDPTR) do_typecast(expr1, expr2.type()); if(c_type2==VOIDPTR) do_typecast(expr2, expr1.type()); } }
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); }
void c_typecastt::implicit_typecast_arithmetic( exprt &expr1, exprt &expr2) { const typet &type1=ns.follow(expr1.type()); const typet &type2=ns.follow(expr2.type()); c_typet c_type1=minimum_promotion(type1), c_type2=minimum_promotion(type2); c_typet max_type=std::max(c_type1, c_type2); if(max_type==LARGE_SIGNED_INT || max_type==LARGE_UNSIGNED_INT) { // get the biggest width of both unsigned width1=type1.get_int(ID_width); unsigned width2=type2.get_int(ID_width); // produce type typet result_type; if(width1==width2) { if(max_type==LARGE_SIGNED_INT) result_type=signedbv_typet(width1); else result_type=unsignedbv_typet(width1); } else if(width1>width2) result_type=type1; else // width1<width2 result_type=type2; do_typecast(expr1, result_type); do_typecast(expr2, result_type); return; } else if(max_type==COMPLEX) { if(c_type1==COMPLEX && c_type2==COMPLEX) { // promote to the one with bigger subtype if(get_c_type(type1.subtype())>get_c_type(type2.subtype())) do_typecast(expr2, type1); else do_typecast(expr1, type2); } else if(c_type1==COMPLEX) { assert(c_type1==COMPLEX && c_type2!=COMPLEX); do_typecast(expr2, type1.subtype()); do_typecast(expr2, type1); } else { assert(c_type1!=COMPLEX && c_type2==COMPLEX); do_typecast(expr1, type2.subtype()); do_typecast(expr1, type2); } return; } else if(max_type==SINGLE || max_type==DOUBLE || max_type==LONGDOUBLE || max_type==FLOAT128) { // Special-case optimisation: // If we have two non-standard sized floats, don't do implicit type // promotion if we can possibly avoid it. if(type1==type2) return; } implicit_typecast_arithmetic(expr1, max_type); implicit_typecast_arithmetic(expr2, max_type); if(max_type==PTR) { if(c_type1==VOIDPTR) do_typecast(expr1, expr2.type()); if(c_type2==VOIDPTR) do_typecast(expr2, expr1.type()); } }