bool is_string_type(const typet &t) const { return (t.id()==ID_pointer || t.id()==ID_array) && (t.subtype().id()==ID_signedbv || t.subtype().id()==ID_unsignedbv) && (to_bitvector_type(t.subtype()).get_width()==config.ansi_c.char_width); }
void c_typecheck_baset::typecheck_c_bit_field_type(typet &type) { typecheck_type(type.subtype()); exprt &width_expr=static_cast<exprt &>(type.add(ID_size)); typecheck_expr(width_expr); make_constant_index(width_expr); mp_integer i; if(to_integer(width_expr, i)) { err_location(type); throw "failed to convert bit field width"; } if(i<0) { err_location(type); throw "bit field width is negative"; } const typet &base_type=follow(type.subtype()); if(base_type.id()==ID_bool) { if(i>1) { err_location(type); throw "bit field width too large"; } // We don't use bool, as it's really a byte long. type.id(ID_unsignedbv); type.set(ID_width, integer2long(i)); } else if(base_type.id()==ID_signedbv || base_type.id()==ID_unsignedbv || base_type.id()==ID_c_enum) { unsigned width=base_type.get_int(ID_width); if(i>width) { err_location(type); throw "bit field width too large"; } typet tmp(base_type); type.swap(tmp); type.set(ID_width, integer2string(i)); } else { err_location(type); str << "bit field with non-integer type: " << to_string(base_type); throw 0; } }
bool c_typecheck_baset::is_complete_type(const typet &type) const { if(type.id()==ID_incomplete_struct || type.id()==ID_incomplete_union) return false; else if(type.id()==ID_array) { if(to_array_type(type).size().is_nil()) return false; return is_complete_type(type.subtype()); } else if(type.id()==ID_struct || type.id()==ID_union) { const struct_union_typet::componentst &components= to_struct_union_type(type).components(); for(struct_union_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) if(!is_complete_type(it->type())) return false; } else if(type.id()==ID_vector) return is_complete_type(type.subtype()); else if(type.id()==ID_symbol) return is_complete_type(follow(type)); return true; }
bool is_void_pointer(const typet &type) { if(type.id()==ID_pointer) { if(type.subtype().id()==ID_empty) return true; return is_void_pointer(type.subtype()); } else return false; }
exprt gen_one(const typet &type) { const irep_idt type_id=type.id(); exprt result=constant_exprt(type); if(type_id==ID_bool || type_id==ID_rational || type_id==ID_real || type_id==ID_integer || type_id==ID_natural) { result.set(ID_value, ID_1); } else if(type_id==ID_unsignedbv || type_id==ID_signedbv || type_id==ID_c_enum) { std::string value; unsigned width=to_bitvector_type(type).get_width(); for(unsigned i=0; i<width-1; i++) value+='0'; value+='1'; result.set(ID_value, value); } else if(type_id==ID_fixedbv) { fixedbvt fixedbv; fixedbv.spec=to_fixedbv_type(type); fixedbv.from_integer(1); result=fixedbv.to_expr(); } else if(type_id==ID_floatbv) { ieee_floatt ieee_float; ieee_float.spec=to_floatbv_type(type); ieee_float.from_integer(1); result=ieee_float.to_expr(); } else if(type_id==ID_complex) { result=exprt(ID_complex, type); result.operands().resize(2); result.op0()=gen_one(type.subtype()); result.op1()=gen_zero(type.subtype()); } else result.make_nil(); return result; }
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()); }
void cpp_typecheckt::check_template_restrictions( const irept &cpp_name, const irep_idt &final_identifier, const typet &final_type) { if(final_type.id()==ID_template) { // subtype must be class or function if(final_type.subtype().id()!=ID_struct && final_type.subtype().id()!=ID_code) { err_location(cpp_name); str << "template only allowed with classes or functions," " but got `" << to_string(final_type.subtype()) << "'"; throw 0; } } }
void c_typecheck_baset::typecheck_type(typet &type) { // we first convert, and then check // 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) { } else if(type.id()==ID_c_bitfield) typecheck_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); // do a bit of rule checking if(type.get_bool(ID_C_restricted) && type.id()!=ID_pointer && type.id()!=ID_array) { err_location(type); error("only a pointer can be 'restrict'"); throw 0; } }
void java_bytecode_typecheckt::typecheck_type(typet &type) { if(type.id()==ID_symbol) { irep_idt identifier=to_symbol_type(type).get_identifier(); symbol_tablet::symbolst::const_iterator s_it= symbol_table.symbols.find(identifier); // must exist already in the symbol table if(s_it==symbol_table.symbols.end()) { error() << "failed to find type symbol "<< identifier << eom; throw 0; } assert(s_it->second.is_type); } else if(type.id()==ID_pointer) { typecheck_type(type.subtype()); } else if(type.id()==ID_array) { typecheck_type(type.subtype()); typecheck_expr(to_array_type(type).size()); } else if(type.id()==ID_code) { code_typet &code_type=to_code_type(type); typecheck_type(code_type.return_type()); code_typet::parameterst ¶meters=code_type.parameters(); for(code_typet::parameterst::iterator it=parameters.begin(); it!=parameters.end(); it++) typecheck_type(it->type()); } }
bool remove_const_function_pointerst::is_const_type(const typet &type) const { c_qualifierst qualifers(type); if(type.id()==ID_array) { c_qualifierst array_type_qualifers(type.subtype()); return qualifers.is_constant || array_type_qualifers.is_constant; } else { return qualifers.is_constant; } }
exprt gen_zero(const typet &type) { exprt result; const irep_idt type_id=type.id(); result=constant_exprt(type); if(type_id==ID_rational || type_id==ID_real || type_id==ID_integer || type_id==ID_natural || type_id==ID_complex || type_id==ID_c_enum) { result.set(ID_value, ID_0); } else if(type_id==ID_unsignedbv || type_id==ID_signedbv || type_id==ID_verilogbv || type_id==ID_floatbv || type_id==ID_fixedbv) { std::string value; unsigned width=to_bitvector_type(type).get_width(); for(unsigned i=0; i<width; i++) value+='0'; result.set(ID_value, value); } else if(type_id==ID_complex) { result=exprt(ID_complex, type); exprt sub_zero=gen_zero(type.subtype()); result.operands().resize(2, sub_zero); } else if(type_id==ID_bool) { result.make_false(); } else if(type_id==ID_pointer) { result.set(ID_value, ID_NULL); } else result.make_nil(); return result; }
bool restrict_bv_size(typet &type, const size_t width_in_bits) { const irep_idt &type_id=type.id(); if (ID_code == type_id) return restrict_bv_size(to_code_type(type), width_in_bits); if (ID_struct == type_id || ID_union == type_id) return restrict_bv_size(to_struct_union_type(type), width_in_bits); if (static_cast<const typet &>(type).subtype().is_not_nil()) restrict_bv_size(type.subtype(), width_in_bits); if (!is_bv_type(type)) return false; bitvector_typet &bvtype=to_bitvector_type(type); if (width_in_bits >= bvtype.get_width()) return false; to_bitvector_type(type).set_width(width_in_bits); return true; }
bool replace_symbolt::replace(typet &dest) { if(dest.has_subtype()) replace(dest.subtype()); Forall_subtypes(it, dest) replace(*it); if(dest.id()=="struct" || dest.id()=="union") { struct_typet &struct_type = to_struct_type(dest); struct_typet::componentst &components = struct_type.components(); for (struct_typet::componentst::iterator it = components.begin(); it!=components.end(); it++) replace(*it); } else if(dest.is_code()) { code_typet &code_type=to_code_type(dest); code_typet::argumentst &arguments=code_type.arguments(); for (code_typet::argumentst::iterator it = arguments.begin(); it!=arguments.end(); it++) replace(*it); } if(dest.id()=="symbol") { type_mapt::const_iterator it= type_map.find(dest.identifier()); if(it!=type_map.end()) { dest=it->second; return false; } } return true; }
unsigned alignment(const typet &type, const namespacet &ns) { if(type.id()==ID_array || type.id()==ID_incomplete_array) return alignment(type.subtype(), ns); else if(type.id()==ID_struct || type.id()==ID_union) { const struct_union_typet::componentst &components= to_struct_union_type(type).components(); unsigned result=1; // get the max // (should really be the smallest common denominator) for(struct_union_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) result=std::max(result, alignment(it->type(), ns)); return result; } else if(type.id()==ID_unsignedbv || type.id()==ID_signedbv || type.id()==ID_fixedbv || type.id()==ID_floatbv) { unsigned width=type.get_int(ID_width); return width%8?width/8+1:width/8; } else if(type.id()==ID_pointer) { unsigned width=config.ansi_c.pointer_width; return width%8?width/8+1:width/8; } else if(type.id()==ID_symbol) return alignment(ns.follow(type), ns); return 1; }
exprt c_sizeoft::sizeof_rec(const typet &type) { exprt dest; if(type.id()==ID_signedbv || type.id()==ID_unsignedbv || type.id()==ID_floatbv || type.id()==ID_fixedbv || type.id()==ID_c_enum || type.id()==ID_incomplete_c_enum) { // We round up to bytes. // See special treatment for bit-fields below. unsigned bits=type.get_int(ID_width); unsigned bytes=bits/8; if((bits%8)!=0) bytes++; dest=from_integer(bytes, size_type()); } else if(type.id()==ID_pointer) { // the following is an MS extension if(type.get_bool(ID_C_ptr32)) return from_integer(4, size_type()); unsigned bits=config.ansi_c.pointer_width; unsigned bytes=bits/8; if((bits%8)!=0) bytes++; dest=from_integer(bytes, size_type()); } else if(type.id()==ID_bool) { // We fit booleans into a byte. dest=from_integer(1, size_type()); } else if(type.id()==ID_array) { const exprt &size_expr= to_array_type(type).size(); if(size_expr.is_nil()) { // treated like an empty array dest=from_integer(0, size_type()); } else { exprt tmp_dest=sizeof_rec(type.subtype()); if(tmp_dest.is_nil()) return tmp_dest; mp_integer a, b; if(!to_integer(tmp_dest, a) && !to_integer(size_expr, b)) { dest=from_integer(a*b, size_type()); } else { dest.id(ID_mult); dest.type()=size_type(); dest.copy_to_operands(size_expr); dest.move_to_operands(tmp_dest); c_implicit_typecast(dest.op0(), dest.type(), ns); c_implicit_typecast(dest.op1(), dest.type(), ns); } } } else if(type.id()==ID_struct) { const struct_typet::componentst &components= to_struct_type(type).components(); dest=from_integer(0, size_type()); mp_integer bit_field_width=0; for(struct_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) { const typet &sub_type=ns.follow(it->type()); if(it->get_bool(ID_is_type)) { } else if(sub_type.id()==ID_code) { } else if(it->get_is_bit_field()) { // this needs to be a signedbv/unsignedbv/enum if(sub_type.id()!=ID_signedbv && sub_type.id()!=ID_unsignedbv && sub_type.id()!=ID_c_enum) return nil_exprt(); // We just sum them up. // This assumes they are properly padded. bit_field_width+=sub_type.get_int(ID_width); } else { exprt tmp=sizeof_rec(sub_type); if(tmp.is_nil()) return tmp; dest=plus_exprt(dest, tmp); } } if(bit_field_width!=0) dest=plus_exprt(dest, from_integer(bit_field_width/8, size_type())); } else if(type.id()==ID_union) { const irept::subt &components= type.find(ID_components).get_sub(); mp_integer max_size=0; forall_irep(it, components) { if(it->get_bool(ID_is_type)) continue; const typet &sub_type=static_cast<const typet &>(it->find(ID_type)); if(sub_type.id()==ID_code) { } else { exprt tmp=sizeof_rec(sub_type); if(tmp.is_nil()) return tmp; simplify(tmp, ns); mp_integer tmp_int; if(to_integer(tmp, tmp_int)) return static_cast<const exprt &>(get_nil_irep()); if(tmp_int>max_size) max_size=tmp_int; } } dest=from_integer(max_size, size_type()); } else if(type.id()==ID_symbol)
void cpp_declarator_convertert::combine_types( const source_locationt &source_location, const typet &decl_type, symbolt &symbol) { if(symbol.type.id()==decl_type.id() && decl_type.id()==ID_code) { // functions need special treatment due // to argument names, default values, and inlined-ness const code_typet &decl_code_type=to_code_type(decl_type); code_typet &symbol_code_type=to_code_type(symbol.type); if(decl_code_type.get_inlined()) symbol_code_type.set_inlined(true); if(decl_code_type.return_type()==symbol_code_type.return_type() && decl_code_type.parameters().size()==symbol_code_type.parameters().size()) { for(unsigned i=0; i<decl_code_type.parameters().size(); i++) { const code_typet::parametert &decl_parameter=decl_code_type.parameters()[i]; code_typet::parametert &symbol_parameter=symbol_code_type.parameters()[i]; // first check type if(decl_parameter.type()!=symbol_parameter.type()) { // The 'this' parameter of virtual functions mismatches if(i!=0 || !symbol_code_type.get_bool("#is_virtual")) { cpp_typecheck.err_location(source_location); cpp_typecheck.str << "symbol `" << symbol.display_name() << "': parameter " << (i+1) << " type mismatch" << std::endl; cpp_typecheck.str << "previous type: " << cpp_typecheck.to_string(symbol_parameter.type()) << std::endl; cpp_typecheck.str << "new type: " << cpp_typecheck.to_string(decl_parameter.type()); throw 0; } } if(symbol.value.is_nil()) { symbol_parameter.set_base_name(decl_parameter.get_base_name()); symbol_parameter.set_identifier(decl_parameter.get_identifier()); symbol_parameter.add_source_location()=decl_parameter.source_location(); } } // ok return; } } else if(symbol.type==decl_type) return; // ok else if(symbol.type.id()==ID_array && symbol.type.find(ID_size).is_nil() && decl_type.id()==ID_array && symbol.type.subtype()==decl_type.subtype()) { symbol.type = decl_type; return; // ok } cpp_typecheck.err_location(source_location); cpp_typecheck.str << "symbol `" << symbol.display_name() << "' already declared with different type:" << std::endl; cpp_typecheck.str << "original: " << cpp_typecheck.to_string(symbol.type) << std::endl; cpp_typecheck.str << " new: " << cpp_typecheck.to_string(final_type); throw 0; }
void ansi_c_convert_typet::write(typet &type) { type.clear(); // first, do "other" if(!other.empty()) { if( double_cnt || float_cnt || signed_cnt || unsigned_cnt || int_cnt || bool_cnt || short_cnt || char_cnt || int8_cnt || int16_cnt || int32_cnt || int64_cnt || ptr32_cnt || ptr64_cnt || long_cnt) { err_location(location); error("illegal type modifier for defined type"); throw 0; } if(other.size() != 1) { err_location(location); error("illegal combination of defined types"); throw 0; } type.swap(other.front()); } else if(double_cnt || float_cnt) { if( signed_cnt || unsigned_cnt || int_cnt || bool_cnt || int8_cnt || int16_cnt || int32_cnt || int64_cnt || ptr32_cnt || ptr64_cnt || short_cnt || char_cnt) { err_location(location); error("cannot conbine integer type with float"); throw 0; } if(double_cnt && float_cnt) { err_location(location); error("conflicting type modifiers"); throw 0; } if(long_cnt == 0) { if(double_cnt != 0) type = double_type(); else type = float_type(); } else if(long_cnt == 1 || long_cnt == 2) { if(double_cnt != 0) type = long_double_type(); else { err_location(location); error("conflicting type modifiers"); throw 0; } } else { err_location(location); error("illegal type modifier for float"); throw 0; } } else if(bool_cnt) { if( signed_cnt || unsigned_cnt || int_cnt || short_cnt || int8_cnt || int16_cnt || int32_cnt || int64_cnt || ptr32_cnt || ptr64_cnt || char_cnt || long_cnt) { err_location(location); error("illegal type modifier for boolean type"); throw 0; } type.id("bool"); } else if(ptr32_cnt || ptr64_cnt) { type.id("pointer"); type.subtype() = typet("empty"); } else { // it is integer -- signed or unsigned? if(signed_cnt && unsigned_cnt) { err_location(location); error("conflicting type modifiers"); throw 0; } if(unsigned_cnt) type.id("unsignedbv"); else if(signed_cnt) type.id("signedbv"); else { if(char_cnt) type.id(config.ansi_c.char_is_unsigned ? "unsignedbv" : "signedbv"); else type.id("signedbv"); } // get width unsigned width; if(int8_cnt || int16_cnt || int32_cnt || int64_cnt) { if(long_cnt || char_cnt || short_cnt) { err_location(location); error("conflicting type modifiers"); throw 0; } if(int8_cnt) width = 1 * 8; else if(int16_cnt) width = 2 * 8; else if(int32_cnt) width = 4 * 8; else if(int64_cnt) width = 8 * 8; else abort(); } else if(short_cnt) { if(long_cnt || char_cnt) { err_location(location); error("conflicting type modifiers"); throw 0; } width = config.ansi_c.short_int_width; } else if(char_cnt) { if(long_cnt) { err_location(location); error("illegal type modifier for char type"); throw 0; } width = config.ansi_c.char_width; } else if(long_cnt == 0) { width = config.ansi_c.int_width; } else if(long_cnt == 1) { width = config.ansi_c.long_int_width; } else if(long_cnt == 2) { width = config.ansi_c.long_long_int_width; } else { err_location(location); error("illegal type modifier for integer type"); throw 0; } type.width(width); } c_qualifiers.write(type); }
bool string_abstractiont::is_ptr_string_struct(const typet &type) const { return type.id()==ID_pointer && type_eq(type.subtype(), string_struct, ns); }
void ansi_c_convert_typet::read_rec(const typet &type) { if(type.id()==ID_merged_type) { forall_subtypes(it, type) read_rec(*it); } else if(type.id()==ID_signed) signed_cnt++; else if(type.id()==ID_unsigned) unsigned_cnt++; else if(type.id()==ID_ptr32) c_qualifiers.is_ptr32=true; else if(type.id()==ID_ptr64) c_qualifiers.is_ptr64=true; else if(type.id()==ID_volatile) c_qualifiers.is_volatile=true; else if(type.id()==ID_asm) { // These are called 'asm labels' by GCC. // ignore for now } else if(type.id()==ID_const) c_qualifiers.is_constant=true; else if(type.id()==ID_restrict) c_qualifiers.is_restricted=true; else if(type.id()==ID_atomic) c_qualifiers.is_atomic=true; else if(type.id()==ID_atomic_type_specifier) { // this gets turned into the qualifier, uh c_qualifiers.is_atomic=true; read_rec(type.subtype()); } else if(type.id()==ID_char) char_cnt++; else if(type.id()==ID_int) int_cnt++; else if(type.id()==ID_int8) int8_cnt++; else if(type.id()==ID_int16) int16_cnt++; else if(type.id()==ID_int32) int32_cnt++; else if(type.id()==ID_int64) int64_cnt++; else if(type.id()==ID_gcc_float128) gcc_float128_cnt++; else if(type.id()==ID_gcc_int128) gcc_int128_cnt++; else if(type.id()==ID_gcc_attribute_mode) { gcc_attribute_mode=type; } else if(type.id()==ID_gcc_attribute) { } else if(type.id()==ID_msc_based) { const exprt &as_expr=static_cast<const exprt &>(static_cast<const irept &>(type)); assert(as_expr.operands().size()==1); msc_based=as_expr.op0(); } else if(type.id()==ID_custom_bv) { bv_cnt++; const exprt &size_expr= static_cast<const exprt &>(type.find(ID_size)); bv_width=size_expr; } else if(type.id()==ID_custom_floatbv) { floatbv_cnt++; const exprt &size_expr= static_cast<const exprt &>(type.find(ID_size)); const exprt &fsize_expr= static_cast<const exprt &>(type.find(ID_f)); bv_width=size_expr; fraction_width=fsize_expr; } else if(type.id()==ID_custom_fixedbv) { fixedbv_cnt++; const exprt &size_expr= static_cast<const exprt &>(type.find(ID_size)); const exprt &fsize_expr= static_cast<const exprt &>(type.find(ID_f)); bv_width=size_expr; fraction_width=fsize_expr; } else if(type.id()==ID_short) short_cnt++; else if(type.id()==ID_long) long_cnt++; else if(type.id()==ID_double) double_cnt++; else if(type.id()==ID_float) float_cnt++; else if(type.id()==ID_c_bool) c_bool_cnt++; else if(type.id()==ID_proper_bool) proper_bool_cnt++; else if(type.id()==ID_complex) complex_cnt++; else if(type.id()==ID_static) c_storage_spec.is_static=true; else if(type.id()==ID_thread_local) c_storage_spec.is_thread_local=true; else if(type.id()==ID_inline) c_storage_spec.is_inline=true; else if(type.id()==ID_extern) c_storage_spec.is_extern=true; else if(type.id()==ID_typedef) c_storage_spec.is_typedef=true; else if(type.id()==ID_register) c_storage_spec.is_register=true; else if(type.id()==ID_auto) { // ignore } else if(type.id()==ID_packed) packed=true; else if(type.id()==ID_aligned) { aligned=true; // may come with size or not if(type.find(ID_size).is_nil()) alignment=exprt(ID_default); else alignment=static_cast<const exprt &>(type.find(ID_size)); } else if(type.id()==ID_transparent_union) { c_qualifiers.is_transparent_union=true; } else if(type.id()==ID_vector) vector_size=to_vector_type(type).size(); else if(type.id()==ID_void) { // we store 'void' as 'empty' typet tmp=type; tmp.id(ID_empty); other.push_back(tmp); } else if(type.id()==ID_msc_declspec) { const exprt &as_expr= static_cast<const exprt &>(static_cast<const irept &>(type)); forall_operands(it, as_expr) { // these are symbols const irep_idt &id=it->get(ID_identifier); if(id=="thread") c_storage_spec.is_thread_local=true; else if(id=="align") { assert(it->operands().size()==1); aligned=true; alignment=it->op0(); } } } else
void cpp_typecheckt::typecheck_type(typet &type) { assert(!type.id().empty()); assert(type.is_not_nil()); try { cpp_convert_plain_type(type); } catch(const char *err) { error().source_location=type.source_location(); error() << err << eom; throw 0; } catch(const std::string &err) { error().source_location=type.source_location(); error() << err << eom; throw 0; } if(type.id()==ID_cpp_name) { c_qualifierst qualifiers(type); cpp_namet cpp_name; cpp_name.swap(type); exprt symbol_expr=resolve( cpp_name, cpp_typecheck_resolvet::wantt::TYPE, cpp_typecheck_fargst()); if(symbol_expr.id()!=ID_type) { error().source_location=type.source_location(); error() << "error: expected type" << eom; throw 0; } type=symbol_expr.type(); assert(type.is_not_nil()); if(type.get_bool(ID_C_constant)) qualifiers.is_constant = true; qualifiers.write(type); } else if(type.id()==ID_struct || type.id()==ID_union) { typecheck_compound_type(to_struct_union_type(type)); } else if(type.id()==ID_pointer) { // the pointer might have a qualifier, but do subtype first typecheck_type(type.subtype()); // Check if it is a pointer-to-member if(type.find("to-member").is_not_nil()) { // these can point either to data members or member functions // of a class typet &class_object=static_cast<typet &>(type.add("to-member")); if(class_object.id()==ID_cpp_name) { assert(class_object.get_sub().back().id()=="::"); class_object.get_sub().pop_back(); } typecheck_type(class_object); // there may be parameters if this is a pointer to member function if(type.subtype().id()==ID_code) { irept::subt ¶meters=type.subtype().add(ID_parameters).get_sub(); if(parameters.empty() || parameters.front().get(ID_C_base_name)!=ID_this) { // Add 'this' to the parameters exprt a0(ID_parameter); a0.set(ID_C_base_name, ID_this); a0.type().id(ID_pointer); a0.type().subtype() = class_object; parameters.insert(parameters.begin(), a0); } } } } else if(type.id()==ID_array) { exprt &size_expr=to_array_type(type).size(); if(size_expr.is_not_nil()) { typecheck_expr(size_expr); simplify(size_expr, *this); } typecheck_type(type.subtype()); if(type.subtype().get_bool(ID_C_constant)) type.set(ID_C_constant, true); if(type.subtype().get_bool(ID_C_volatile)) type.set(ID_C_volatile, true); } else if(type.id()==ID_code) { code_typet &code_type=to_code_type(type); typecheck_type(code_type.return_type()); code_typet::parameterst ¶meters=code_type.parameters(); for(auto ¶m : parameters) { typecheck_type(param.type()); // see if there is a default value if(param.has_default_value()) { typecheck_expr(param.default_value()); implicit_typecast(param.default_value(), param.type()); } } } else if(type.id()==ID_template) { typecheck_type(type.subtype()); } else if(type.id()==ID_c_enum) { typecheck_enum_type(type); } else if(type.id()==ID_c_enum_tag) { } else if(type.id()==ID_c_bit_field) { typecheck_c_bit_field_type(to_c_bit_field_type(type)); } else if(type.id()==ID_unsignedbv || type.id()==ID_signedbv || type.id()==ID_bool || type.id()==ID_floatbv || type.id()==ID_fixedbv || type.id()==ID_empty) { } else if(type.id()==ID_symbol) { } else if(type.id()==ID_constructor || type.id()==ID_destructor) { } else if(type.id()=="cpp-cast-operator") { } else if(type.id()=="cpp-template-type") { } else if(type.id()==ID_typeof) { exprt e=static_cast<const exprt &>(type.find(ID_expr_arg)); if(e.is_nil()) { typet tmp_type= static_cast<const typet &>(type.find(ID_type_arg)); if(tmp_type.id()==ID_cpp_name) { // this may be ambiguous -- it can be either a type or // an expression cpp_typecheck_fargst fargs; exprt symbol_expr=resolve( to_cpp_name(static_cast<const irept &>(tmp_type)), cpp_typecheck_resolvet::wantt::BOTH, fargs); type=symbol_expr.type(); } else { typecheck_type(tmp_type); type=tmp_type; } } else { typecheck_expr(e); type=e.type(); } } else if(type.id()==ID_decltype) { exprt e=static_cast<const exprt &>(type.find(ID_expr_arg)); typecheck_expr(e); type=e.type(); } else if(type.id()==ID_unassigned) { // ignore, for template parameter guessing } else if(type.id()==ID_template_class_instance) { // ok (internally generated) } else if(type.id()==ID_block_pointer) { // This is an Apple extension for lambda-like constructs. // http://thirdcog.eu/pwcblocks/ } else if(type.id()==ID_nullptr) { } else { error().source_location=type.source_location(); error() << "unexpected cpp type: " << type.pretty() << eom; throw 0; } assert(type.is_not_nil()); }
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(); }
void cpp_typecheckt::typecheck_type(typet &type) { assert(type.id() != ""); assert(type.is_not_nil()); try { cpp_convert_plain_type(type); } catch(const char *error) { err_location(type); str << error; throw 0; } catch(const std::string &error) { err_location(type); str << error; throw 0; } if(type.id() == "cpp-name") { c_qualifierst qualifiers(type); cpp_namet cpp_name; cpp_name.swap(type); exprt symbol_expr = resolve(cpp_name, cpp_typecheck_resolvet::TYPE, cpp_typecheck_fargst()); if(symbol_expr.id() != "type") { err_location(type); str << "error: expected type"; throw 0; } type = symbol_expr.type(); assert(type.is_not_nil()); if(type.cmt_constant()) qualifiers.is_constant = true; qualifiers.write(type); } else if(type.id() == "struct" || type.id() == "union") { typecheck_compound_type(type); } else if(type.id() == "pointer") { // the pointer might have a qualifier, but do subtype first typecheck_type(type.subtype()); // Check if it is a pointer-to-member if(type.find("to-member").is_not_nil()) { // these can point either to data members or member functions // of a class typet &class_object = static_cast<typet &>(type.add("to-member")); if(class_object.id() == "cpp-name") { assert(class_object.get_sub().back().id() == "::"); class_object.get_sub().pop_back(); } typecheck_type(class_object); // there may be arguments if this is a pointer to member function if(type.subtype().id() == "code") { irept::subt &args = type.subtype().add("arguments").get_sub(); if(args.empty() || args.front().cmt_base_name() != "this") { // Add 'this' to the arguments exprt a0("argument"); a0.cmt_base_name("this"); a0.type().id("pointer"); a0.type().subtype() = class_object; args.insert(args.begin(), a0); } } } // now do qualifier if(type.find("#qualifier").is_not_nil()) { typet &t = static_cast<typet &>(type.add("#qualifier")); cpp_convert_plain_type(t); c_qualifierst q(t); q.write(type); } type.remove("#qualifier"); } else if(type.id() == "array") { exprt &size_expr = to_array_type(type).size(); if(size_expr.is_nil()) type.id("incomplete_array"); else typecheck_expr(size_expr); // TODO: If is a incomplete_array, it should always // have initializers, except for catch declaration typecheck_type(type.subtype()); if(type.subtype().cmt_constant()) type.cmt_constant(true); if(type.subtype().cmt_volatile()) type.set("#volatile", true); } else if(type.id() == "code") { code_typet &code_type = to_code_type(type); typecheck_type(code_type.return_type()); code_typet::argumentst &arguments = code_type.arguments(); for(auto &argument : arguments) { typecheck_type(argument.type()); // see if there is a default value if(argument.has_default_value()) { typecheck_expr(argument.default_value()); implicit_typecast(argument.default_value(), argument.type()); } } } else if(type.id() == "template") { typecheck_type(type.subtype()); } else if(type.id() == "c_enum") { typecheck_enum_type(type); } else if( type.id() == "unsignedbv" || type.id() == "signedbv" || type.id() == "bool" || type.id() == "floatbv" || type.id() == "fixedbv" || type.id() == "empty") { } else if(type.id() == "symbol") { } else if(type.id() == "constructor" || type.id() == "destructor") { } else if(type.id() == "cpp-cast-operator") { } else if(type.id() == "cpp-template-type") { } else if(type.id() == "typeof") { exprt e = static_cast<const exprt &>(type.find("expr")); if(e.is_nil()) { typet tmp_type = static_cast<const typet &>(type.find("sizeof-type")); if(tmp_type.id() == "cpp-name") { // this may be ambiguous -- it can be either a type or // an expression cpp_typecheck_fargst fargs; exprt symbol_expr = resolve( to_cpp_name(static_cast<const irept &>(tmp_type)), cpp_typecheck_resolvet::BOTH, fargs); type = symbol_expr.type(); } else { typecheck_type(tmp_type); type = tmp_type; } } else { typecheck_expr(e); type = e.type(); } } else if(type.id() == "decltype") { exprt e = static_cast<const exprt &>(type.find("expr_arg")); typecheck_expr(e); type = e.type(); } else if(type.id() == "unassigned") { // ignore, for template argument guessing } else if(type.id() == "ellipsis") { } else { err_location(type); str << "unexpected type: " << type.pretty(); throw 0; } assert(type.is_not_nil()); }
bool boolbvt::type_conversion( const typet &src_type, const bvt &src, const typet &dest_type, bvt &dest) { bvtypet dest_bvtype=get_bvtype(dest_type); bvtypet src_bvtype=get_bvtype(src_type); if(src_bvtype==IS_C_BIT_FIELD) return type_conversion( c_bit_field_replacement_type(to_c_bit_field_type(src_type), ns), src, dest_type, dest); if(dest_bvtype==IS_C_BIT_FIELD) return type_conversion( src_type, src, c_bit_field_replacement_type(to_c_bit_field_type(dest_type), ns), dest); std::size_t src_width=src.size(); std::size_t dest_width=boolbv_width(dest_type); if(dest_width==0 || src_width==0) return true; dest.clear(); dest.reserve(dest_width); if(dest_type.id()==ID_complex) { if(src_type==dest_type.subtype()) { forall_literals(it, src) dest.push_back(*it); // pad with zeros for(std::size_t i=src.size(); i<dest_width; i++) dest.push_back(const_literal(false)); return false; } else if(src_type.id()==ID_complex) { // recursively do both halfs bvt lower, upper, lower_res, upper_res; lower.assign(src.begin(), src.begin()+src.size()/2); upper.assign(src.begin()+src.size()/2, src.end()); type_conversion(ns.follow(src_type.subtype()), lower, ns.follow(dest_type.subtype()), lower_res); type_conversion(ns.follow(src_type.subtype()), upper, ns.follow(dest_type.subtype()), upper_res); assert(lower_res.size()+upper_res.size()==dest_width); dest=lower_res; dest.insert(dest.end(), upper_res.begin(), upper_res.end()); return false; } } if(src_type.id()==ID_complex) { assert(dest_type.id()!=ID_complex); if(dest_type.id()==ID_signedbv || dest_type.id()==ID_unsignedbv || dest_type.id()==ID_floatbv || dest_type.id()==ID_fixedbv || dest_type.id()==ID_c_enum || dest_type.id()==ID_c_enum_tag || dest_type.id()==ID_bool) { // A cast from complex x to real T // is (T) __real__ x. bvt tmp_src(src); tmp_src.resize(src.size()/2); // cut off imag part return type_conversion(src_type.subtype(), tmp_src, dest_type, dest); } } switch(dest_bvtype) { case IS_RANGE: if(src_bvtype==IS_UNSIGNED || src_bvtype==IS_SIGNED || src_bvtype==IS_C_BOOL) { mp_integer dest_from=to_range_type(dest_type).get_from(); if(dest_from==0) { // do zero extension dest.resize(dest_width); for(std::size_t i=0; i<dest.size(); i++) dest[i]=(i<src.size()?src[i]:const_literal(false)); return false; } } else if(src_bvtype==IS_RANGE) // range to range { mp_integer src_from=to_range_type(src_type).get_from(); mp_integer dest_from=to_range_type(dest_type).get_from(); if(dest_from==src_from) { // do zero extension, if needed dest=bv_utils.zero_extension(src, dest_width); return false; } else { // need to do arithmetic: add src_from-dest_from mp_integer offset=src_from-dest_from; dest= bv_utils.add( bv_utils.zero_extension(src, dest_width), bv_utils.build_constant(offset, dest_width)); } return false; } break; case IS_FLOAT: // to float { float_utilst float_utils(prop); switch(src_bvtype) { case IS_FLOAT: // float to float // we don't have a rounding mode here, // which is why we refuse. break; case IS_SIGNED: // signed to float case IS_C_ENUM: float_utils.spec=to_floatbv_type(dest_type); dest=float_utils.from_signed_integer(src); return false; case IS_UNSIGNED: // unsigned to float case IS_C_BOOL: // _Bool to float float_utils.spec=to_floatbv_type(dest_type); dest=float_utils.from_unsigned_integer(src); return false; case IS_BV: assert(src_width==dest_width); dest=src; return false; default: if(src_type.id()==ID_bool) { // bool to float // build a one ieee_floatt f; f.spec=to_floatbv_type(dest_type); f.from_integer(1); dest=convert_bv(f.to_expr()); assert(src_width==1); Forall_literals(it, dest) *it=prop.land(*it, src[0]); return false; } } } break; case IS_FIXED: if(src_bvtype==IS_FIXED) { // fixed to fixed std::size_t dest_fraction_bits=to_fixedbv_type(dest_type).get_fraction_bits(), dest_int_bits=dest_width-dest_fraction_bits; std::size_t op_fraction_bits=to_fixedbv_type(src_type).get_fraction_bits(), op_int_bits=src_width-op_fraction_bits; dest.resize(dest_width); // i == position after dot // i == 0: first position after dot for(std::size_t i=0; i<dest_fraction_bits; i++) { // position in bv std::size_t p=dest_fraction_bits-i-1; if(i<op_fraction_bits) dest[p]=src[op_fraction_bits-i-1]; else dest[p]=const_literal(false); // zero padding } for(std::size_t i=0; i<dest_int_bits; i++) { // position in bv std::size_t p=dest_fraction_bits+i; assert(p<dest_width); if(i<op_int_bits) dest[p]=src[i+op_fraction_bits]; else dest[p]=src[src_width-1]; // sign extension } return false; } else if(src_bvtype==IS_BV) { assert(src_width==dest_width); dest=src; return false; } else if(src_bvtype==IS_UNSIGNED || src_bvtype==IS_SIGNED || src_bvtype==IS_C_BOOL || src_bvtype==IS_C_ENUM) { // integer to fixed std::size_t dest_fraction_bits= to_fixedbv_type(dest_type).get_fraction_bits(); for(std::size_t i=0; i<dest_fraction_bits; i++) dest.push_back(const_literal(false)); // zero padding for(std::size_t i=0; i<dest_width-dest_fraction_bits; i++) { literalt l; if(i<src_width) l=src[i]; else { if(src_bvtype==IS_SIGNED || src_bvtype==IS_C_ENUM) l=src[src_width-1]; // sign extension else l=const_literal(false); // zero extension } dest.push_back(l); } return false; } else if(src_type.id()==ID_bool) { // bool to fixed std::size_t fraction_bits= to_fixedbv_type(dest_type).get_fraction_bits(); assert(src_width==1); for(std::size_t i=0; i<dest_width; i++) { if(i==fraction_bits) dest.push_back(src[0]); else dest.push_back(const_literal(false)); } return false; } break; case IS_UNSIGNED: case IS_SIGNED: case IS_C_ENUM: switch(src_bvtype) { case IS_FLOAT: // float to integer // we don't have a rounding mode here, // which is why we refuse. break; case IS_FIXED: // fixed to integer { std::size_t op_fraction_bits= to_fixedbv_type(src_type).get_fraction_bits(); for(std::size_t i=0; i<dest_width; i++) { if(i<src_width-op_fraction_bits) dest.push_back(src[i+op_fraction_bits]); else { if(dest_bvtype==IS_SIGNED) dest.push_back(src[src_width-1]); // sign extension else dest.push_back(const_literal(false)); // zero extension } } // we might need to round up in case of negative numbers // e.g., (int)(-1.00001)==1 bvt fraction_bits_bv=src; fraction_bits_bv.resize(op_fraction_bits); literalt round_up= prop.land(prop.lor(fraction_bits_bv), src.back()); dest=bv_utils.incrementer(dest, round_up); return false; } case IS_UNSIGNED: // integer to integer case IS_SIGNED: case IS_C_ENUM: case IS_C_BOOL: { // We do sign extension for any source type // that is signed, independently of the // destination type. // E.g., ((short)(ulong)(short)-1)==-1 bool sign_extension= src_bvtype==IS_SIGNED || src_bvtype==IS_C_ENUM; for(std::size_t i=0; i<dest_width; i++) { if(i<src_width) dest.push_back(src[i]); else if(sign_extension) dest.push_back(src[src_width-1]); // sign extension else dest.push_back(const_literal(false)); } return false; } case IS_VERILOG_UNSIGNED: // verilog_unsignedbv to signed/unsigned/enum { for(std::size_t i=0; i<dest_width; i++) { std::size_t src_index=i*2; // we take every second bit if(src_index<src_width) dest.push_back(src[src_index]); else // always zero-extend dest.push_back(const_literal(false)); } return false; } break; case IS_VERILOG_SIGNED: // verilog_signedbv to signed/unsigned/enum { for(std::size_t i=0; i<dest_width; i++) { std::size_t src_index=i*2; // we take every second bit if(src_index<src_width) dest.push_back(src[src_index]); else // always sign-extend dest.push_back(src.back()); } return false; } break; default: if(src_type.id()==ID_bool) { // bool to integer assert(src_width==1); for(std::size_t i=0; i<dest_width; i++) { if(i==0) dest.push_back(src[0]); else dest.push_back(const_literal(false)); } return false; } } break; case IS_VERILOG_UNSIGNED: if(src_bvtype==IS_UNSIGNED || src_bvtype==IS_C_BOOL || src_type.id()==ID_bool) { for(std::size_t i=0, j=0; i<dest_width; i+=2, j++) { if(j<src_width) dest.push_back(src[j]); else dest.push_back(const_literal(false)); dest.push_back(const_literal(false)); } return false; } else if(src_bvtype==IS_SIGNED) { for(std::size_t i=0, j=0; i<dest_width; i+=2, j++) { if(j<src_width) dest.push_back(src[j]); else dest.push_back(src.back()); dest.push_back(const_literal(false)); } return false; } else if(src_bvtype==IS_VERILOG_UNSIGNED) { // verilog_unsignedbv to verilog_unsignedbv dest=src; if(dest_width<src_width) dest.resize(dest_width); else { dest=src; while(dest.size()<dest_width) { dest.push_back(const_literal(false)); dest.push_back(const_literal(false)); } } return false; } break; case IS_BV: assert(src_width==dest_width); dest=src; return false; case IS_C_BOOL: dest.resize(dest_width, const_literal(false)); if(src_bvtype==IS_FLOAT) { float_utilst float_utils(prop); float_utils.spec=to_floatbv_type(src_type); dest[0]=!float_utils.is_zero(src); } else if(src_bvtype==IS_C_BOOL) dest[0]=src[0]; else dest[0]=!bv_utils.is_zero(src); return false; default: if(dest_type.id()==ID_array) { if(src_width==dest_width) { dest=src; return false; } } else if(dest_type.id()==ID_struct) { const struct_typet &dest_struct = to_struct_type(dest_type); if(src_type.id()==ID_struct) { // we do subsets dest.resize(dest_width, const_literal(false)); const struct_typet &op_struct = to_struct_type(src_type); const struct_typet::componentst &dest_comp= dest_struct.components(); const struct_typet::componentst &op_comp= op_struct.components(); // build offset maps offset_mapt op_offsets, dest_offsets; build_offset_map(op_struct, op_offsets); build_offset_map(dest_struct, dest_offsets); // build name map typedef std::map<irep_idt, unsigned> op_mapt; op_mapt op_map; for(std::size_t i=0; i<op_comp.size(); i++) op_map[op_comp[i].get_name()]=i; // now gather required fields for(std::size_t i=0; i<dest_comp.size(); i++) { std::size_t offset=dest_offsets[i]; std::size_t comp_width=boolbv_width(dest_comp[i].type()); if(comp_width==0) continue; op_mapt::const_iterator it= op_map.find(dest_comp[i].get_name()); if(it==op_map.end()) { // not found // filling with free variables for(std::size_t j=0; j<comp_width; j++) dest[offset+j]=prop.new_variable(); } else { // found if(dest_comp[i].type()!=dest_comp[it->second].type()) { // filling with free variables for(std::size_t j=0; j<comp_width; j++) dest[offset+j]=prop.new_variable(); } else { std::size_t op_offset=op_offsets[it->second]; for(std::size_t j=0; j<comp_width; j++) dest[offset+j]=src[op_offset+j]; } } } return false; } } } return true; }
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; }
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; }
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; }
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); }
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; }
void cpp_typecheckt::typecheck_enum_type(typet &type) { // first save qualifiers c_qualifierst qualifiers; qualifiers.read(type); cpp_enum_typet &enum_type=to_cpp_enum_type(type); bool anonymous=!enum_type.has_tag(); irep_idt base_name; if(anonymous) { // we fabricate a tag based on the enum constants contained base_name=enum_type.generate_anon_tag(); } else { const cpp_namet &tag=enum_type.tag(); if(tag.is_simple_name()) base_name=tag.get_base_name(); else { err_location(type); throw "enum tag is expected to be a simple name"; } } bool has_body=enum_type.has_body(); bool tag_only_declaration=enum_type.get_tag_only_declaration(); cpp_scopet &dest_scope= tag_scope(base_name, has_body, tag_only_declaration); const irep_idt symbol_name= dest_scope.prefix+"tag-"+id2string(base_name); // check if we have it symbol_tablet::symbolst::iterator previous_symbol= symbol_table.symbols.find(symbol_name); if(previous_symbol!=symbol_table.symbols.end()) { // we do! symbolt &symbol=previous_symbol->second; if(has_body) { err_location(type); str << "error: enum symbol `" << base_name << "' declared previously\n"; str << "location of previous definition: " << symbol.location; throw 0; } } else if(has_body) { std::string pretty_name= cpp_scopes.current_scope().prefix+id2string(base_name); // C++11 enumerations have an underlying type, // which defaults to int. // enums without underlying type may be 'packed'. if(type.subtype().is_nil()) type.subtype()=signed_int_type(); else { typecheck_type(type.subtype()); if(type.subtype().id()==ID_signedbv || type.subtype().id()==ID_unsignedbv) { } else { err_location(type); str << "underlying type must be integral"; throw 0; } } symbolt symbol; symbol.name=symbol_name; symbol.base_name=base_name; symbol.value.make_nil(); symbol.location=type.source_location(); symbol.mode=ID_cpp; symbol.module=module; symbol.type.swap(type); symbol.is_type=true; symbol.is_macro=false; symbol.pretty_name=pretty_name; // move early, must be visible before doing body symbolt *new_symbol; if(symbol_table.move(symbol, new_symbol)) throw "cpp_typecheckt::typecheck_enum_type: symbol_table.move() failed"; // put into scope cpp_idt &scope_identifier= cpp_scopes.put_into_scope(*new_symbol, dest_scope); scope_identifier.id_class=cpp_idt::CLASS; typecheck_enum_body(*new_symbol); } else { err_location(type); str << "use of enum `" << base_name << "' without previous declaration"; throw 0; } // create enum tag expression, and add the qualifiers type=c_enum_tag_typet(symbol_name); qualifiers.write(type); }
std::string type2name(const typet &type) { std::string result; // qualifiers first if(type.get_bool(ID_C_constant)) result+="c"; if(type.get_bool(ID_C_restricted)) result+="r"; if(type.get_bool(ID_C_volatile)) result+="v"; if(type.id()==irep_idt()) throw "Empty type encountered."; else if(type.id()==ID_empty) result+="V"; else if(type.id()==ID_signedbv) result+="S" + type.get_string(ID_width); else if(type.id()==ID_unsignedbv) result+="U" + type.get_string(ID_width); else if(type.id()==ID_bool) result+="B"; else if(type.id()==ID_integer) result+="I"; else if(type.id()==ID_real) result+="R"; else if(type.id()==ID_complex) result+="C"; else if(type.id()==ID_floatbv) result+="F" + type.get_string(ID_width); else if(type.id()==ID_fixedbv) result+="X" + type.get_string(ID_width); else if(type.id()==ID_natural) result+="N"; else if(type.id()==ID_pointer) result+="*"; else if(type.id()==ID_reference) result+="&"; else if(type.id()==ID_code) { const code_typet &t=to_code_type(type); const code_typet::argumentst arguments=t.arguments(); result+="P("; for(code_typet::argumentst::const_iterator it=arguments.begin(); it!=arguments.end(); it++) { result+=type2name(it->type()); result+="'" + id2string(it->get_identifier()) + "'|"; } result.resize(result.size()-1); result+=")"; } else if(type.id()==ID_array) { const array_typet &t=to_array_type(type); if(t.size().is_nil()) result+="ARR?"; else result+="ARR"+t.size().get_string(ID_value); } else if(type.id()==ID_symbol) { result+="SYM#"+type.get_string(ID_identifier)+"#"; } else if(type.id()==ID_struct || type.id()==ID_union) { if(type.id()==ID_struct) result+="ST"; if(type.id()==ID_union) result+="UN"; const struct_union_typet &t=to_struct_union_type(type); const struct_union_typet::componentst &components = t.components(); result+="["; for(struct_union_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) { if(it!=components.begin()) result+="|"; result+=type2name(it->type()); result+="'"+it->get_string(ID_name)+"'|"; } result+="]"; } else if(type.id()==ID_incomplete_struct) result +="ST?"; else if(type.id()==ID_incomplete_union) result +="UN?"; else if(type.id()==ID_c_enum) result +="EN"+type.get_string(ID_width); else if(type.id()==ID_incomplete_c_enum) result +="EN?"; else if(type.id()==ID_c_bitfield) result+="BF"+type.get_string(ID_size); else if(type.id()==ID_vector) result+="VEC"+type.get_string(ID_size); else throw (std::string("Unknown type '") + type.id_string() + "' encountered."); if(type.has_subtype()) { result+="{"; result+=type2name(type.subtype()); result+="}"; } if(type.has_subtypes()) { result+="$"; forall_subtypes(it, type) { result+=type2name(*it); result+="|"; }