bool check_c_implicit_typecast( const typet &src_type, const typet &dest_type) { // check qualifiers if(src_type.id()==ID_pointer && dest_type.id()==ID_pointer && src_type.subtype().get_bool(ID_C_constant) && !dest_type.subtype().get_bool(ID_C_constant)) return true; if(src_type==dest_type) return false; const irep_idt &src_type_id=src_type.id(); if(src_type_id==ID_natural) { if(dest_type.id()==ID_bool) return false; if(dest_type.id()==ID_integer) return false; if(dest_type.id()==ID_real) return false; if(dest_type.id()==ID_complex) return false; if(dest_type.id()==ID_unsignedbv) return false; if(dest_type.id()==ID_signedbv) return false; if(dest_type.id()==ID_floatbv) return false; if(dest_type.id()==ID_complex) return false; } else if(src_type_id==ID_integer) { if(dest_type.id()==ID_bool) return false; if(dest_type.id()==ID_real) return false; if(dest_type.id()==ID_complex) return false; if(dest_type.id()==ID_unsignedbv) return false; if(dest_type.id()==ID_signedbv) return false; if(dest_type.id()==ID_floatbv) return false; if(dest_type.id()==ID_fixedbv) return false; if(dest_type.id()==ID_pointer) return false; if(dest_type.id()==ID_complex) return false; } else if(src_type_id==ID_real) { if(dest_type.id()==ID_bool) return false; if(dest_type.id()==ID_complex) return false; if(dest_type.id()==ID_floatbv) return false; if(dest_type.id()==ID_fixedbv) return false; if(dest_type.id()==ID_complex) return false; } else if(src_type_id==ID_rational) { if(dest_type.id()==ID_bool) return false; if(dest_type.id()==ID_complex) return false; if(dest_type.id()==ID_floatbv) return false; if(dest_type.id()==ID_fixedbv) return false; if(dest_type.id()==ID_complex) return false; } else if(src_type_id==ID_bool) { if(dest_type.id()==ID_integer) return false; if(dest_type.id()==ID_real) return false; if(dest_type.id()==ID_unsignedbv) return false; if(dest_type.id()==ID_signedbv) return false; if(dest_type.id()==ID_pointer) return false; if(dest_type.id()==ID_floatbv) return false; if(dest_type.id()==ID_fixedbv) return false; if(dest_type.id()==ID_c_enum) return false; if(dest_type.id()==ID_complex) return false; } else if(src_type_id==ID_unsignedbv || src_type_id==ID_signedbv || src_type_id==ID_c_enum || src_type_id==ID_incomplete_c_enum) { if(dest_type.id()==ID_unsignedbv) return false; if(dest_type.id()==ID_bool) return false; if(dest_type.id()==ID_integer) return false; if(dest_type.id()==ID_real) return false; if(dest_type.id()==ID_rational) return false; if(dest_type.id()==ID_signedbv) return false; if(dest_type.id()==ID_floatbv) return false; if(dest_type.id()==ID_fixedbv) return false; if(dest_type.id()==ID_pointer) return false; if(dest_type.id()==ID_c_enum) return false; if(dest_type.id()==ID_incomplete_c_enum) return false; if(dest_type.id()==ID_complex) return false; } else if(src_type_id==ID_floatbv || src_type_id==ID_fixedbv) { if(dest_type.id()==ID_bool) return false; if(dest_type.id()==ID_integer) return false; if(dest_type.id()==ID_real) return false; if(dest_type.id()==ID_rational) return false; if(dest_type.id()==ID_signedbv) return false; if(dest_type.id()==ID_unsignedbv) return false; if(dest_type.id()==ID_floatbv) return false; if(dest_type.id()==ID_fixedbv) return false; if(dest_type.id()==ID_complex) return false; } else if(src_type_id==ID_array || src_type_id==ID_pointer) { if(dest_type.id()==ID_pointer) { const irept &dest_subtype=dest_type.subtype(); const irept &src_subtype =src_type.subtype(); if(src_subtype==dest_subtype) return false; else if(is_void_pointer(src_type) || // from void to anything is_void_pointer(dest_type)) // to void from anything return false; } if(dest_type.id()==ID_array && src_type.subtype()==dest_type.subtype()) return false; if(dest_type.id()==ID_bool) return false; if(dest_type.id()==ID_unsignedbv) return false; if(dest_type.id()==ID_signedbv) return false; } else if(src_type_id==ID_vector) { if(dest_type.id()==ID_vector) return false; } else if(src_type_id==ID_complex) { if(dest_type.id()==ID_complex) { // We convert between complex types if we convert between // their component types. if(!check_c_implicit_typecast(src_type.subtype(), dest_type.subtype())) return false; } } return true; }
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); }
bool check_c_implicit_typecast( const typet &src_type, const typet &dest_type) { // check qualifiers if(src_type.id()==ID_pointer && dest_type.id()==ID_pointer && src_type.subtype().get_bool(ID_C_constant) && !dest_type.subtype().get_bool(ID_C_constant)) return true; if(src_type==dest_type) return false; const irep_idt &src_type_id=src_type.id(); if(src_type_id==ID_c_bit_field) return check_c_implicit_typecast(src_type.subtype(), dest_type); if(dest_type.id()==ID_c_bit_field) return check_c_implicit_typecast(src_type, dest_type.subtype()); if(src_type_id==ID_natural) { if(dest_type.id()==ID_bool) return false; if(dest_type.id()==ID_c_bool) return false; if(dest_type.id()==ID_integer) return false; if(dest_type.id()==ID_real) return false; if(dest_type.id()==ID_complex) return false; if(dest_type.id()==ID_unsignedbv) return false; if(dest_type.id()==ID_signedbv) return false; if(dest_type.id()==ID_floatbv) return false; if(dest_type.id()==ID_complex) return false; } else if(src_type_id==ID_integer) { if(dest_type.id()==ID_bool) return false; if(dest_type.id()==ID_c_bool) return false; if(dest_type.id()==ID_real) return false; if(dest_type.id()==ID_complex) return false; if(dest_type.id()==ID_unsignedbv) return false; if(dest_type.id()==ID_signedbv) return false; if(dest_type.id()==ID_floatbv) return false; if(dest_type.id()==ID_fixedbv) return false; if(dest_type.id()==ID_pointer) return false; if(dest_type.id()==ID_complex) return false; } else if(src_type_id==ID_real) { if(dest_type.id()==ID_bool) return false; if(dest_type.id()==ID_c_bool) return false; if(dest_type.id()==ID_complex) return false; if(dest_type.id()==ID_floatbv) return false; if(dest_type.id()==ID_fixedbv) return false; if(dest_type.id()==ID_complex) return false; } else if(src_type_id==ID_rational) { if(dest_type.id()==ID_bool) return false; if(dest_type.id()==ID_c_bool) return false; if(dest_type.id()==ID_complex) return false; if(dest_type.id()==ID_floatbv) return false; if(dest_type.id()==ID_fixedbv) return false; if(dest_type.id()==ID_complex) return false; } else if(src_type_id==ID_bool) { if(dest_type.id()==ID_c_bool) return false; if(dest_type.id()==ID_integer) return false; if(dest_type.id()==ID_real) return false; if(dest_type.id()==ID_unsignedbv) return false; if(dest_type.id()==ID_signedbv) return false; if(dest_type.id()==ID_pointer) return false; if(dest_type.id()==ID_floatbv) return false; if(dest_type.id()==ID_fixedbv) return false; if(dest_type.id()==ID_c_enum) return false; if(dest_type.id()==ID_c_enum_tag) return false; if(dest_type.id()==ID_complex) return false; } else if(src_type_id==ID_unsignedbv || src_type_id==ID_signedbv || src_type_id==ID_c_enum || src_type_id==ID_c_enum_tag || src_type_id==ID_incomplete_c_enum || src_type_id==ID_c_bool) { if(dest_type.id()==ID_unsignedbv) return false; if(dest_type.id()==ID_bool) return false; if(dest_type.id()==ID_c_bool) return false; if(dest_type.id()==ID_integer) return false; if(dest_type.id()==ID_real) return false; if(dest_type.id()==ID_rational) return false; if(dest_type.id()==ID_signedbv) return false; if(dest_type.id()==ID_floatbv) return false; if(dest_type.id()==ID_fixedbv) return false; if(dest_type.id()==ID_pointer) return false; if(dest_type.id()==ID_c_enum) return false; if(dest_type.id()==ID_c_enum_tag) return false; if(dest_type.id()==ID_incomplete_c_enum) return false; if(dest_type.id()==ID_complex) return false; } else if(src_type_id==ID_floatbv || src_type_id==ID_fixedbv) { if(dest_type.id()==ID_bool) return false; if(dest_type.id()==ID_c_bool) return false; if(dest_type.id()==ID_integer) return false; if(dest_type.id()==ID_real) return false; if(dest_type.id()==ID_rational) return false; if(dest_type.id()==ID_signedbv) return false; if(dest_type.id()==ID_unsignedbv) return false; if(dest_type.id()==ID_floatbv) return false; if(dest_type.id()==ID_fixedbv) return false; if(dest_type.id()==ID_complex) return false; } else if(src_type_id==ID_complex) { if(dest_type.id()==ID_complex) return check_c_implicit_typecast(src_type.subtype(), dest_type.subtype()); else { // 6.3.1.7, par 2: // When a value of complex type is converted to a real type, the // imaginary part of the complex value is discarded and the value of the // real part is converted according to the conversion rules for the // corresponding real type. return check_c_implicit_typecast(src_type.subtype(), dest_type); } } else if(src_type_id==ID_array || src_type_id==ID_pointer) { if(dest_type.id()==ID_pointer) { const irept &dest_subtype=dest_type.subtype(); const irept &src_subtype =src_type.subtype(); if(src_subtype==dest_subtype) return false; else if(is_void_pointer(src_type) || // from void to anything is_void_pointer(dest_type)) // to void from anything return false; } if(dest_type.id()==ID_array && src_type.subtype()==dest_type.subtype()) return false; if(dest_type.id()==ID_bool) return false; if(dest_type.id()==ID_c_bool) return false; if(dest_type.id()==ID_unsignedbv) return false; if(dest_type.id()==ID_signedbv) return false; } else if(src_type_id==ID_vector) { if(dest_type.id()==ID_vector) return false; } else if(src_type_id==ID_complex) { if(dest_type.id()==ID_complex) { // We convert between complex types if we convert between // their component types. if(!check_c_implicit_typecast(src_type.subtype(), dest_type.subtype())) return false; } } return true; }