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 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 c_typecheck_baset::designator_enter( const typet &type, designatort &designator) { designatort::entryt entry; entry.type=type; entry.index=0; const typet &full_type=follow(type); if(full_type.id()==ID_struct) { const struct_typet &struct_type=to_struct_type(full_type); entry.size=struct_type.components().size(); entry.subtype.make_nil(); for(struct_typet::componentst::const_iterator it=struct_type.components().begin(); it!=struct_type.components().end(); ++it) { if(it->type().id()!=ID_code && !it->get_is_padding()) { entry.subtype=it->type(); break; } ++entry.index; } } else if(full_type.id()==ID_union) { const union_typet &union_type=to_union_type(full_type); if(union_type.components().empty()) { entry.size=0; entry.subtype.make_nil(); } else { // The default is to unitialize using the first member of the // union. entry.size=1; entry.subtype=union_type.components().front().type(); } } else if(full_type.id()==ID_array) { const array_typet &array_type=to_array_type(full_type); if(array_type.size().is_nil()) { entry.size=0; entry.subtype=array_type.subtype(); } else { mp_integer array_size; if(to_integer(array_type.size(), array_size)) { err_location(array_type.size()); error() << "array has non-constant size `" << to_string(array_type.size()) << "'" << eom; throw 0; } entry.size=integer2size_t(array_size); entry.subtype=array_type.subtype(); } } else if(full_type.id()==ID_vector) { const vector_typet &vector_type=to_vector_type(full_type); mp_integer vector_size; if(to_integer(vector_type.size(), vector_size)) { err_location(vector_type.size()); error() << "vector has non-constant size `" << to_string(vector_type.size()) << "'" << eom; throw 0; } entry.size=integer2size_t(vector_size); entry.subtype=vector_type.subtype(); } else assert(false); designator.push_entry(entry); }
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; }
exprt path_symex_statet::expand_structs_and_arrays(const exprt &src) { #ifdef DEBUG std::cout << "expand_structs_and_arrays: " << from_expr(var_map.ns, "", src) << '\n'; #endif const typet &src_type=var_map.ns.follow(src.type()); if(src_type.id()==ID_struct) // src is a struct { const struct_typet &struct_type=to_struct_type(src_type); const struct_typet::componentst &components=struct_type.components(); struct_exprt result(src.type()); result.operands().resize(components.size()); // split it up into components for(unsigned i=0; i<components.size(); i++) { const typet &subtype=components[i].type(); const irep_idt &component_name=components[i].get_name(); exprt new_src; if(src.id()==ID_struct) // struct constructor? { assert(src.operands().size()==components.size()); new_src=src.operands()[i]; } else new_src=member_exprt(src, component_name, subtype); // recursive call result.operands()[i]=expand_structs_and_arrays(new_src); } return result; // done } else if(src_type.id()==ID_array) // src is an array { const array_typet &array_type=to_array_type(src_type); const typet &subtype=array_type.subtype(); if(array_type.size().is_constant()) { mp_integer size; if(to_integer(array_type.size(), size)) throw "failed to convert array size"; std::size_t size_int=integer2size_t(size); array_exprt result(array_type); result.operands().resize(size_int); // split it up into elements for(std::size_t i=0; i<size_int; ++i) { exprt index=from_integer(i, array_type.size().type()); exprt new_src=index_exprt(src, index, subtype); // array constructor? if(src.id()==ID_array) new_src=simplify_expr(new_src, var_map.ns); // recursive call result.operands()[i]=expand_structs_and_arrays(new_src); } return result; // done } else { // TODO: variable-sized array } } else if(src_type.id()==ID_vector) // src is a vector { const vector_typet &vector_type=to_vector_type(src_type); const typet &subtype=vector_type.subtype(); if(!vector_type.size().is_constant()) throw "vector with non-constant size"; mp_integer size; if(to_integer(vector_type.size(), size)) throw "failed to convert vector size"; std::size_t size_int=integer2size_t(size); vector_exprt result(vector_type); exprt::operandst &operands=result.operands(); operands.resize(size_int); // split it up into elements for(std::size_t i=0; i<size_int; ++i) { exprt index=from_integer(i, vector_type.size().type()); exprt new_src=index_exprt(src, index, subtype); // vector constructor? if(src.id()==ID_vector) new_src=simplify_expr(new_src, var_map.ns); // recursive call operands[i]=expand_structs_and_arrays(new_src); } return result; // done } return src; }
exprt path_symex_statet::instantiate_rec( const exprt &src, bool propagate) { #ifdef DEBUG std::cout << "instantiate_rec: " << from_expr(var_map.ns, "", src) << std::endl; #endif const typet &src_type=var_map.ns.follow(src.type()); if(src_type.id()==ID_struct) // src is a struct { const struct_typet &struct_type=to_struct_type(src_type); const struct_typet::componentst &components=struct_type.components(); struct_exprt result(src.type()); result.operands().resize(components.size()); // split it up into components for(unsigned i=0; i<components.size(); i++) { const typet &subtype=components[i].type(); const irep_idt &component_name=components[i].get_name(); exprt new_src; if(src.id()==ID_struct) // struct constructor? { assert(src.operands().size()==components.size()); new_src=src.operands()[i]; } else new_src=member_exprt(src, component_name, subtype); // recursive call result.operands()[i]=instantiate_rec(new_src, propagate); } return result; // done } else if(src_type.id()==ID_array) // src is an array { const array_typet &array_type=to_array_type(src_type); const typet &subtype=array_type.subtype(); if(array_type.size().is_constant()) { mp_integer size; if(to_integer(array_type.size(), size)) throw "failed to convert array size"; unsigned long long size_int=integer2unsigned(size); array_exprt result(array_type); result.operands().resize(size_int); // split it up into elements for(unsigned long long i=0; i<size_int; ++i) { exprt index=from_integer(i, array_type.size().type()); exprt new_src=index_exprt(src, index, subtype); // array constructor? if(src.id()==ID_array) new_src=simplify_expr(new_src, var_map.ns); // recursive call result.operands()[i]=instantiate_rec(new_src, propagate); } return result; // done } else { // TODO } } else if(src_type.id()==ID_vector) // src is a vector { const vector_typet &vector_type=to_vector_type(src_type); const typet &subtype=vector_type.subtype(); if(!vector_type.size().is_constant()) throw "vector with non-constant size"; mp_integer size; if(to_integer(vector_type.size(), size)) throw "failed to convert vector size"; unsigned long long int size_int=integer2unsigned(size); vector_exprt result(vector_type); exprt::operandst &operands=result.operands(); operands.resize(size_int); // split it up into elements for(unsigned long long i=0; i<size_int; ++i) { exprt index=from_integer(i, vector_type.size().type()); exprt new_src=index_exprt(src, index, subtype); // vector constructor? if(src.id()==ID_vector) new_src=simplify_expr(new_src, var_map.ns); // recursive call operands[i]=instantiate_rec(new_src, propagate); } return result; // done } // check whether this is a symbol(.member|[index])* { exprt tmp_symbol_member_index= read_symbol_member_index(src, propagate); if(tmp_symbol_member_index.is_not_nil()) return tmp_symbol_member_index; // yes! } if(src.id()==ID_address_of) { assert(src.operands().size()==1); exprt tmp=src; tmp.op0()=instantiate_rec_address(tmp.op0(), propagate); return tmp; } else if(src.id()==ID_sideeffect) { // could be done separately const irep_idt &statement=to_side_effect_expr(src).get_statement(); if(statement==ID_nondet) { irep_idt id="symex::nondet"+i2string(var_map.nondet_count); var_map.nondet_count++; return symbol_exprt(id, src.type()); } else throw "instantiate_rec: unexpected side effect "+id2string(statement); } else if(src.id()==ID_dereference) { // dereferencet has run already, so we should only be left with // integer addresses. Will transform into __CPROVER_memory[] // eventually. } else if(src.id()==ID_index) { // avoids indefinite recursion above return src; } else if(src.id()==ID_member) { const typet &compound_type= var_map.ns.follow(to_member_expr(src).struct_op().type()); if(compound_type.id()==ID_struct) { // avoids indefinite recursion above return src; } else if(compound_type.id()==ID_union) { member_exprt tmp=to_member_expr(src); tmp.struct_op()=instantiate_rec(tmp.struct_op(), propagate); return tmp; } else { throw "member expects struct or union type"+src.pretty(); } } if(!src.has_operands()) return src; exprt src2=src; // recursive calls on structure of 'src' Forall_operands(it, src2) { exprt tmp_op=instantiate_rec(*it, propagate); *it=tmp_op; }
void goto_checkt::bounds_check( const index_exprt &expr, const guardt &guard) { if(!enable_bounds_check) return; if(expr.find("bounds_check").is_not_nil() && !expr.get_bool("bounds_check")) return; typet array_type=ns.follow(expr.array().type()); if(array_type.id()==ID_pointer) return; // done by the pointer code else if(array_type.id()==ID_incomplete_array) throw "index got incomplete array"; else if(array_type.id()!=ID_array && array_type.id()!=ID_vector) throw "bounds check expected array or vector type, got " +array_type.id_string(); std::string name=array_name(expr.array()); const exprt &index=expr.index(); object_descriptor_exprt ode; ode.build(expr, ns); if(index.type().id()!=ID_unsignedbv) { // we undo typecasts to signedbv if(index.id()==ID_typecast && index.operands().size()==1 && index.op0().type().id()==ID_unsignedbv) { // ok } else { mp_integer i; if(!to_integer(index, i) && i>=0) { // ok } else { exprt effective_offset=ode.offset(); if(ode.root_object().id()==ID_dereference) { exprt p_offset=pointer_offset( to_dereference_expr(ode.root_object()).pointer()); assert(p_offset.type()==effective_offset.type()); effective_offset=plus_exprt(p_offset, effective_offset); } exprt zero=gen_zero(ode.offset().type()); assert(zero.is_not_nil()); // the final offset must not be negative binary_relation_exprt inequality(effective_offset, ID_ge, zero); add_guarded_claim( inequality, name+" lower bound", "array bounds", expr.find_source_location(), expr, guard); } } } if(ode.root_object().id()==ID_dereference) { const exprt &pointer= to_dereference_expr(ode.root_object()).pointer(); if_exprt size( dynamic_object(pointer), typecast_exprt(dynamic_size(ns), object_size(pointer).type()), object_size(pointer)); plus_exprt effective_offset(ode.offset(), pointer_offset(pointer)); assert(effective_offset.op0().type()==effective_offset.op1().type()); assert(effective_offset.type()==size.type()); binary_relation_exprt inequality(effective_offset, ID_lt, size); or_exprt precond( and_exprt( dynamic_object(pointer), not_exprt(malloc_object(pointer, ns))), inequality); add_guarded_claim( precond, name+" upper bound", "array bounds", expr.find_source_location(), expr, guard); return; } const exprt &size=array_type.id()==ID_array ? to_array_type(array_type).size() : to_vector_type(array_type).size(); if(size.is_nil()) { // Linking didn't complete, we don't have a size. // Not clear what to do. } else if(size.id()==ID_infinity) { } else if(size.is_zero() && expr.array().id()==ID_member) { // a variable sized struct member } else { binary_relation_exprt inequality(index, ID_lt, size); // typecast size if(inequality.op1().type()!=inequality.op0().type()) inequality.op1().make_typecast(inequality.op0().type()); // typecast size if(inequality.op1().type()!=inequality.op0().type()) inequality.op1().make_typecast(inequality.op0().type()); add_guarded_claim( inequality, name+" upper bound", "array bounds", expr.find_source_location(), expr, guard); } }
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; } }
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) { // ignore for now } else if(type.id()==ID_const) c_qualifiers.is_constant=true; else if(type.id()==ID_restricted) c_qualifiers.is_restricted=true; 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) { const exprt &size_expr= static_cast<const exprt &>(type.find(ID_size)); if(size_expr.id()=="__QI__") gcc_mode_QI=true; else if(size_expr.id()=="__HI__") gcc_mode_HI=true; else if(size_expr.id()=="__SI__") gcc_mode_SI=true; else if(size_expr.id()=="__DI__") gcc_mode_DI=true; else { // we ignore without whining } } else if(type.id()==ID_bv) { bv_cnt++; const exprt &size_expr= static_cast<const exprt &>(type.find(ID_size)); mp_integer size_int; if(to_integer(size_expr, size_int)) { err_location(location); error("bit vector width has to be constant"); throw 0; } if(size_int<1 || size_int>1024) { err_location(location); error("bit vector width invalid"); throw 0; } bv_width=integer2long(size_int); } 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_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 other.push_back(type); }
const boolbv_widtht::entryt &boolbv_widtht::get_entry(const typet &type) const { // check cache first std::pair<cachet::iterator, bool> cache_result= cache.insert(std::pair<typet, entryt>(type, entryt())); entryt &entry=cache_result.first->second; if(!cache_result.second) // found! return entry; entry.total_width=0; const irep_idt type_id=type.id(); if(type_id==ID_struct) { const struct_typet::componentst &components= to_struct_type(type).components(); std::size_t offset=0; entry.members.resize(components.size()); for(std::size_t i=0; i<entry.members.size(); i++) { std::size_t sub_width=operator()(components[i].type()); entry.members[i].offset=offset; entry.members[i].width=sub_width; offset+=sub_width; } entry.total_width=offset; } else if(type_id==ID_union) { const union_typet::componentst &components= to_union_type(type).components(); entry.members.resize(components.size()); std::size_t max_width=0; for(std::size_t i=0; i<entry.members.size(); i++) { std::size_t sub_width=operator()(components[i].type()); entry.members[i].width=sub_width; max_width=std::max(max_width, sub_width); } entry.total_width=max_width; } else if(type_id==ID_bool) entry.total_width=1; else if(type_id==ID_c_bool) { entry.total_width=to_c_bool_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_signedbv) { entry.total_width=to_signedbv_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_unsignedbv) { entry.total_width=to_unsignedbv_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_floatbv) { entry.total_width=to_floatbv_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_fixedbv) { entry.total_width=to_fixedbv_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_bv) { entry.total_width=to_bv_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_verilogbv) { // we encode with two bits entry.total_width=type.get_unsigned_int(ID_width)*2; assert(entry.total_width!=0); } else if(type_id==ID_range) { mp_integer from=string2integer(type.get_string(ID_from)), to=string2integer(type.get_string(ID_to)); mp_integer size=to-from+1; if(size>=1) { entry.total_width=integer2unsigned(address_bits(size)); assert(entry.total_width!=0); } } else if(type_id==ID_array) { const array_typet &array_type=to_array_type(type); std::size_t sub_width=operator()(array_type.subtype()); mp_integer array_size; if(to_integer(array_type.size(), array_size)) { // we can still use the theory of arrays for this entry.total_width=0; } else { mp_integer total=array_size*sub_width; if(total>(1<<30)) // realistic limit throw "array too large for flattening"; entry.total_width=integer2unsigned(total); } } else if(type_id==ID_vector) { const vector_typet &vector_type=to_vector_type(type); std::size_t sub_width=operator()(vector_type.subtype()); mp_integer vector_size; if(to_integer(vector_type.size(), vector_size)) { // we can still use the theory of arrays for this entry.total_width=0; } else { mp_integer total=vector_size*sub_width; if(total>(1<<30)) // realistic limit throw "vector too large for flattening"; entry.total_width=integer2unsigned(vector_size*sub_width); } } else if(type_id==ID_complex) { std::size_t sub_width=operator()(type.subtype()); entry.total_width=integer2unsigned(2*sub_width); } else if(type_id==ID_code) { } else if(type_id==ID_enum) { // get number of necessary bits std::size_t size=type.find(ID_elements).get_sub().size(); entry.total_width=integer2unsigned(address_bits(size)); assert(entry.total_width!=0); } else if(type_id==ID_c_enum) { // these have a subtype entry.total_width=type.subtype().get_unsigned_int(ID_width); assert(entry.total_width!=0); } else if(type_id==ID_incomplete_c_enum) { // no width } else if(type_id==ID_pointer || type_id==ID_reference) { entry.total_width=config.ansi_c.pointer_width; } else if(type_id==ID_symbol) entry=get_entry(ns.follow(type)); else if(type_id==ID_struct_tag) entry=get_entry(ns.follow_tag(to_struct_tag_type(type))); else if(type_id==ID_union_tag) entry=get_entry(ns.follow_tag(to_union_tag_type(type))); else if(type_id==ID_c_enum_tag) entry=get_entry(ns.follow_tag(to_c_enum_tag_type(type))); else if(type_id==ID_c_bit_field) { entry.total_width=to_c_bit_field_type(type).get_width(); } return entry; }
json_objectt json( const typet &type, const namespacet &ns) { if(type.id()==ID_symbol) return json(ns.follow(type), ns); json_objectt result; if(type.id()==ID_unsignedbv) { result["name"]=json_stringt("integer"); result["width"]= json_numbert(i2string(to_unsignedbv_type(type).get_width())); } else if(type.id()==ID_signedbv) { result["name"]=json_stringt("integer"); result["width"]=json_numbert(i2string(to_signedbv_type(type).get_width())); } else if(type.id()==ID_floatbv) { result["name"]=json_stringt("float"); result["width"]=json_numbert(i2string(to_floatbv_type(type).get_width())); } else if(type.id()==ID_bv) { result["name"]=json_stringt("integer"); result["width"]=json_numbert(i2string(to_bv_type(type).get_width())); } else if(type.id()==ID_c_bit_field) { result["name"]=json_stringt("integer"); result["width"]= json_numbert(i2string(to_c_bit_field_type(type).get_width())); } else if(type.id()==ID_c_enum_tag) { // we return the base type return json(ns.follow_tag(to_c_enum_tag_type(type)).subtype(), ns); } else if(type.id()==ID_fixedbv) { result["name"]=json_stringt("fixed"); result["width"]=json_numbert(i2string(to_fixedbv_type(type).get_width())); } else if(type.id()==ID_pointer) { result["name"]=json_stringt("pointer"); result["subtype"]=json(type.subtype(), ns); } else if(type.id()==ID_bool) { result["name"]=json_stringt("boolean"); } else if(type.id()==ID_array) { result["name"]=json_stringt("array"); result["subtype"]=json(type.subtype(), ns); } else if(type.id()==ID_vector) { result["name"]=json_stringt("vector"); result["subtype"]=json(type.subtype(), ns); result["size"]=json(to_vector_type(type).size(), ns); } else if(type.id()==ID_struct) { result["name"]=json_stringt("struct"); json_arrayt &members=result["members"].make_array(); const struct_typet::componentst &components= to_struct_type(type).components(); for(const auto & it : components) { json_objectt &e=members.push_back().make_object(); e["name"]=json_stringt(id2string(it.get_name())); e["type"]=json(it.type(), ns); } } else if(type.id()==ID_union) { result["name"]=json_stringt("union"); json_arrayt &members=result["members"].make_array(); const union_typet::componentst &components= to_union_type(type).components(); for(const auto & it : components) { json_objectt &e=members.push_back().make_object(); e["name"]=json_stringt(id2string(it.get_name())); e["type"]=json(it.type(), ns); } } else result["name"]=json_stringt("unknown"); return result; }