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 base_type_rec( typet &type, const namespacet &ns, std::set<irep_idt> &symb) { if(type.id()==ID_symbol || type.id()==ID_c_enum_tag || type.id()==ID_struct_tag || type.id()==ID_union_tag) { const symbolt *symbol; if(!ns.lookup(type.get(ID_identifier), symbol) && symbol->is_type && !symbol->type.is_nil()) { type=symbol->type; base_type_rec(type, ns, symb); // recursive call return; } } else if(type.id()==ID_array) { base_type_rec(to_array_type(type).subtype(), ns, symb); } else if(type.id()==ID_struct || type.id()==ID_union) { struct_union_typet::componentst &components= to_struct_union_type(type).components(); for(auto &component : components) base_type_rec(component.type(), ns, symb); } else if(type.id()==ID_pointer) { typet &subtype=to_pointer_type(type).subtype(); // we need to avoid running into an infinite loop if(subtype.id()==ID_symbol || subtype.id()==ID_c_enum_tag || subtype.id()==ID_struct_tag || subtype.id()==ID_union_tag) { const irep_idt &id=subtype.get(ID_identifier); if(symb.find(id)!=symb.end()) return; symb.insert(id); base_type_rec(subtype, ns, symb); symb.erase(id); } else base_type_rec(subtype, ns, symb); } }
bool dereferencet::type_compatible( const typet &object_type, const typet &dereference_type) const { if(dereference_type.id()==ID_empty) return true; // always ok if(base_type_eq(object_type, dereference_type, ns)) return true; // ok, they just match // check for struct prefixes if(object_type.id()==ID_struct && dereference_type.id()==ID_struct) { if(to_struct_type(dereference_type).is_prefix_of( to_struct_type(object_type))) return true; // ok, dreference_type is a prefix of object_type } // any code is ok if(dereference_type.id()==ID_code && object_type.id()==ID_code) return true; // bit vectors of same size are ok if((object_type.id()==ID_signedbv || object_type.id()==ID_unsignedbv) && (dereference_type.id()==ID_signedbv || dereference_type.id()==ID_unsignedbv)) { return object_type.get(ID_width)==dereference_type.get(ID_width); } // Any pointer to pointer is always ok, // but should likely check that width is the same. if(object_type.id()==ID_pointer && dereference_type.id()==ID_pointer) return true; // really different return false; }
void bv_spect::from_type(const typet &type) { if(type.id()==ID_unsignedbv) is_signed=false; else if(type.id()==ID_signedbv) is_signed=true; else assert(0); width=atoi(type.get(ID_width).c_str()); }
static std::string type2name_symbol( const typet &type, const namespacet &ns, symbol_numbert &symbol_number) { const irep_idt &identifier=type.get(ID_identifier); const symbolt *symbol; if(ns.lookup(identifier, symbol)) return "SYM#"+id2string(identifier)+"#"; assert(symbol && symbol->is_type); if(symbol->type.id()!=ID_struct && symbol->type.id()!=ID_union) return type2name(symbol->type, ns, symbol_number); std::string result; // assign each symbol a number when seen for the first time std::pair<symbol_numbert::iterator, bool> entry= symbol_number.insert(std::make_pair( identifier, std::make_pair(symbol_number.size(), true))); // new entry, add definition if(entry.second) { result="SYM#"+std::to_string(entry.first->second.first); result+="={"; result+=type2name(symbol->type, ns, symbol_number); result+='}'; entry.first->second.second=false; } #if 0 // in recursion, print the shorthand only else if(entry.first->second.second) result="SYM#"+std::to_string(entry.first->second.first); // entering recursion else { entry.first->second.second=true; result=type2name(symbol->type, ns, symbol_number); entry.first->second.second=false; } #else // shorthand only as structs/unions are always symbols else
void c_typecastt::do_typecast(exprt &expr, const typet &type) { // special case: array -> pointer is actually // something like address_of const typet &expr_type=ns.follow(expr.type()); if(expr_type.id()==ID_array) { index_exprt index; index.array()=expr; index.index()=gen_zero(index_type()); index.type()=expr_type.subtype(); expr=address_of_exprt(index); if(ns.follow(expr.type())!=ns.follow(type)) expr.make_typecast(type); return; } if(expr_type!=type) { // C booleans are special: we compile to ?0:1 if(type.get(ID_C_c_type)==ID_bool) { if(expr_type.id()==ID_bool) // bool -> _Bool { exprt result=if_exprt(expr, gen_one(type), gen_zero(type)); expr.swap(result); } else // * -> _Bool { equal_exprt equal_zero(expr, gen_zero(expr_type)); exprt result=if_exprt(equal_zero, gen_zero(type), gen_one(type)); expr.swap(result); } } else { expr.make_typecast(type); } } }
void c_typecastt::do_typecast(exprt &expr, const typet &dest_type) { // special case: array -> pointer is actually // something like address_of const typet &src_type=ns.follow(expr.type()); if(src_type.id()==ID_array) { index_exprt index; index.array()=expr; index.index()=gen_zero(index_type()); index.type()=src_type.subtype(); expr=address_of_exprt(index); if(ns.follow(expr.type())!=ns.follow(dest_type)) expr.make_typecast(dest_type); return; } if(src_type!=dest_type) { // C booleans are special; we produce the // explicit comparision with zero. // Note that this requires ieee_float_notequal // in case of floating-point numbers. if(dest_type.get(ID_C_c_type)==ID_bool) { expr=is_not_zero(expr, ns); expr.make_typecast(dest_type); } else if(dest_type.id()==ID_bool) { expr=is_not_zero(expr, ns); } else { expr.make_typecast(dest_type); } } }
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; }
c_typecastt::c_typet c_typecastt::get_c_type( const typet &type) { unsigned width=type.get_int(ID_width); if(type.id()==ID_signedbv) { if(width<=config.ansi_c.char_width) return CHAR; else if(width<=config.ansi_c.short_int_width) return SHORT; else if(width<=config.ansi_c.int_width) return INT; else if(width<=config.ansi_c.long_int_width) return LONG; else if(width<=config.ansi_c.long_long_int_width) return LONGLONG; else return LARGE_SIGNED_INT; } else if(type.id()==ID_unsignedbv) { if(type.get(ID_C_c_type)==ID_bool) return BOOL; if(width<=config.ansi_c.char_width) return UCHAR; else if(width<=config.ansi_c.short_int_width) return USHORT; else if(width<=config.ansi_c.int_width) return UINT; else if(width<=config.ansi_c.long_int_width) return ULONG; else if(width<=config.ansi_c.long_long_int_width) return ULONGLONG; else return LARGE_UNSIGNED_INT; } else if(type.id()==ID_bool) return BOOL; else if(type.id()==ID_floatbv || type.id()==ID_fixedbv) { if(width<=config.ansi_c.single_width) return SINGLE; else if(width<=config.ansi_c.double_width) return DOUBLE; else if(width<=config.ansi_c.long_double_width) return LONGDOUBLE; } else if(type.id()==ID_pointer) { if(type.subtype().id()==ID_empty) return VOIDPTR; else return PTR; } else if(type.id()==ID_array) { return PTR; } else if(type.id()==ID_c_enum || type.id()==ID_incomplete_c_enum) { return INT; } else if(type.id()==ID_symbol) return get_c_type(ns.follow(type)); else if(type.id()==ID_rational) return RATIONAL; else if(type.id()==ID_real) return REAL; else if(type.id()==ID_complex) return COMPLEX; return OTHER; }
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; } }
unsigned bv_width(const typet &type) { return atoi(type.get(ID_width).c_str()); }
bool base_type_eqt::base_type_eq_rec( const typet &type1, const typet &type2) { if(type1==type2) return true; #if 0 std::cout << "T1: " << type1.pretty() << std::endl; std::cout << "T2: " << type2.pretty() << std::endl; #endif // loop avoidance if((type1.id()==ID_symbol || type1.id()==ID_c_enum_tag || type1.id()==ID_struct_tag || type1.id()==ID_union_tag) && type2.id()==type1.id()) { // already in same set? if(identifiers.make_union( type1.get(ID_identifier), type2.get(ID_identifier))) return true; } if(type1.id()==ID_symbol || type1.id()==ID_c_enum_tag || type1.id()==ID_struct_tag || type1.id()==ID_union_tag) { const symbolt &symbol= ns.lookup(type1.get(ID_identifier)); if(!symbol.is_type) return false; return base_type_eq_rec(symbol.type, type2); } if(type2.id()==ID_symbol || type2.id()==ID_c_enum_tag || type2.id()==ID_struct_tag || type2.id()==ID_union_tag) { const symbolt &symbol= ns.lookup(type2.get(ID_identifier)); if(!symbol.is_type) return false; return base_type_eq_rec(type1, symbol.type); } if(type1.id()!=type2.id()) return false; if(type1.id()==ID_struct || type1.id()==ID_union) { const struct_union_typet::componentst &components1= to_struct_union_type(type1).components(); const struct_union_typet::componentst &components2= to_struct_union_type(type2).components(); if(components1.size()!=components2.size()) return false; for(unsigned i=0; i<components1.size(); i++) { const typet &subtype1=components1[i].type(); const typet &subtype2=components2[i].type(); if(!base_type_eq_rec(subtype1, subtype2)) return false; if(components1[i].get_name()!=components2[i].get_name()) return false; } return true; } else if(type1.id()==ID_incomplete_struct) { return true; } else if(type1.id()==ID_incomplete_union) { return true; } else if(type1.id()==ID_code) { const code_typet::parameterst ¶meters1= to_code_type(type1).parameters(); const code_typet::parameterst ¶meters2= to_code_type(type2).parameters(); if(parameters1.size()!=parameters2.size()) return false; for(unsigned i=0; i<parameters1.size(); i++) { const typet &subtype1=parameters1[i].type(); const typet &subtype2=parameters2[i].type(); if(!base_type_eq_rec(subtype1, subtype2)) return false; } const typet &return_type1=to_code_type(type1).return_type(); const typet &return_type2=to_code_type(type2).return_type(); if(!base_type_eq_rec(return_type1, return_type2)) return false; return true; } else if(type1.id()==ID_pointer) { return base_type_eq_rec( to_pointer_type(type1).subtype(), to_pointer_type(type2).subtype()); } else if(type1.id()==ID_array) { if(!base_type_eq_rec( to_array_type(type1).subtype(), to_array_type(type2).subtype())) return false; if(to_array_type(type1).size()!=to_array_type(type2).size()) return false; return true; } else if(type1.id()==ID_incomplete_array) { return base_type_eq_rec( to_incomplete_array_type(type1).subtype(), to_incomplete_array_type(type2).subtype()); } // the below will go away typet tmp1(type1), tmp2(type2); base_type(tmp1, ns); base_type(tmp2, ns); return tmp1==tmp2; }