bool has_component_rec( const typet &type, const irep_idt &component_name, const namespacet &ns) { const struct_union_typet &struct_union_type= to_struct_union_type(ns.follow(type)); const struct_union_typet::componentst &components= struct_union_type.components(); for(struct_union_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) { if(it->get_name()==component_name) { return true; } else if(it->get_anonymous()) { if(has_component_rec(it->type(), component_name, ns)) return true; } } return false; }
exprt get_component_rec( const exprt &struct_union, const irep_idt &component_name, const namespacet &ns) { const struct_union_typet &struct_union_type= to_struct_union_type(ns.follow(struct_union.type())); const struct_union_typet::componentst &components= struct_union_type.components(); for(struct_union_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) { const typet &type=ns.follow(it->type()); if(it->get_name()==component_name) { return make_member_expr(struct_union, *it, ns); } else if(it->get_anonymous() && (type.id()==ID_struct || type.id()==ID_union)) { exprt tmp=make_member_expr(struct_union, *it, ns); exprt result=get_component_rec(tmp, component_name, ns); if(result.is_not_nil()) return result; } } return nil_exprt(); }
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; }
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); } }
const typet &replace_struct_by_symbol_type(const symbol_tablet &st, const typet &type) { const irep_idt &type_id=type.id(); if (ID_struct != type_id && ID_incomplete_struct != type_id && ID_union != type_id && ID_incomplete_union != type_id) return type; std::string tag(TAG_PREFIX); tag+=id2string(to_struct_union_type(type).get_tag()); return st.lookup(tag).type; }
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; } }
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; }
std::string linkingt::to_string_verbose(const typet &type) { const typet &followed=ns.follow(type); if(followed.id()==ID_struct || followed.id()==ID_union) { std::string result=followed.id_string(); const std::string &tag=followed.get_string(ID_tag); if(tag!="") result+=" "+tag; result+=" {\n"; const struct_union_typet::componentst &components= to_struct_union_type(followed).components(); for(struct_union_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) { const typet &subtype=it->type(); result+=" "; result+=to_string(subtype); result+=" "; if(it->get_base_name()!="") result+=id2string(it->get_base_name()); else result+=id2string(it->get_name()); result+=";\n"; } result+="}"; return result; } else if(followed.id()==ID_pointer) { return to_string_verbose(followed.subtype())+" *"; } return to_string(type); }
typet fence_insertert::type_component(std::list<std::string>::const_iterator it, std::list<std::string>::const_iterator end, const typet& type) { if(it==end) return type; if(type.id()==ID_struct) { const struct_union_typet& str=to_struct_union_type(type); typet comp_type=str.component_type(*it); ++it; return type_component(it, end, comp_type); } if(type.id()==ID_symbol) { return type; } assert(0); }
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; }
designatort c_typecheck_baset::make_designator( const typet &src_type, const exprt &src) { assert(!src.operands().empty()); typet type=src_type; designatort designator; forall_operands(it, src) { const exprt &d_op=*it; designatort::entryt entry; entry.type=type; const typet &full_type=follow(entry.type); if(full_type.id()==ID_array) { if(d_op.id()!=ID_index) { err_location(d_op); error() << "expected array index designator" << eom; throw 0; } assert(d_op.operands().size()==1); exprt tmp_index=d_op.op0(); make_constant_index(tmp_index); mp_integer index, size; if(to_integer(tmp_index, index)) { err_location(d_op.op0()); error() << "expected constant array index designator" << eom; throw 0; } if(to_array_type(full_type).size().is_nil()) size=0; else if(to_integer(to_array_type(full_type).size(), size)) { err_location(d_op.op0()); error() << "expected constant array size" << eom; throw 0; } entry.index=integer2size_t(index); entry.size=integer2size_t(size); entry.subtype=full_type.subtype(); } else if(full_type.id()==ID_struct || full_type.id()==ID_union) { const struct_union_typet &struct_union_type= to_struct_union_type(full_type); if(d_op.id()!=ID_member) { err_location(d_op); error() << "expected member designator" << eom; throw 0; } const irep_idt &component_name=d_op.get(ID_component_name); if(struct_union_type.has_component(component_name)) { // a direct member entry.index=struct_union_type.component_number(component_name); entry.size=struct_union_type.components().size(); entry.subtype=struct_union_type.components()[entry.index].type(); } else { // We will search for anonymous members, // in a loop. This isn't supported by gcc, but icc does allow it. bool found=false, repeat; typet tmp_type=entry.type; do { repeat=false; unsigned number=0; const struct_union_typet::componentst &components= to_struct_union_type(follow(tmp_type)).components(); for(struct_union_typet::componentst::const_iterator c_it=components.begin(); c_it!=components.end(); c_it++, number++) { if(c_it->get_name()==component_name) { // done! entry.index=number; entry.size=components.size(); entry.subtype=components[entry.index].type(); entry.type=tmp_type; } else if(c_it->get_anonymous() && (follow(c_it->type()).id()==ID_struct || follow(c_it->type()).id()==ID_union) && has_component_rec( c_it->type(), component_name, *this)) { entry.index=number; entry.size=components.size(); entry.subtype=c_it->type(); entry.type=tmp_type; tmp_type=entry.subtype; designator.push_entry(entry); found=repeat=true; break; } } } while(repeat); if(!found) { err_location(d_op); error() << "failed to find struct component `" << component_name << "' in initialization of `" << to_string(struct_union_type) << "'" << eom; throw 0; } } } else { err_location(d_op); error() << "designated initializers cannot initialize `" << to_string(full_type) << "'" << eom; throw 0; } type=entry.subtype; designator.push_entry(entry); } assert(!designator.empty()); return designator; }
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 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()); }
void value_sett::get_value_set_rec( const exprt &expr, object_mapt &dest, const std::string &suffix, const typet &original_type, const namespacet &ns) const { #if 0 std::cout << "GET_VALUE_SET_REC EXPR: " << from_expr(ns, "", expr) << "\n"; std::cout << "GET_VALUE_SET_REC SUFFIX: " << suffix << std::endl; #endif const typet &expr_type=ns.follow(expr.type()); if(expr.id()==ID_unknown || expr.id()==ID_invalid) { insert(dest, exprt(ID_unknown, original_type)); } else if(expr.id()==ID_index) { assert(expr.operands().size()==2); const typet &type=ns.follow(expr.op0().type()); assert(type.id()==ID_array || type.id()==ID_incomplete_array); get_value_set_rec(expr.op0(), dest, "[]"+suffix, original_type, ns); } else if(expr.id()==ID_member) { assert(expr.operands().size()==1); const typet &type=ns.follow(expr.op0().type()); assert(type.id()==ID_struct || type.id()==ID_union || type.id()==ID_incomplete_struct || type.id()==ID_incomplete_union); const std::string &component_name= expr.get_string(ID_component_name); get_value_set_rec(expr.op0(), dest, "."+component_name+suffix, original_type, ns); } else if(expr.id()==ID_symbol) { irep_idt identifier=to_symbol_expr(expr).get_identifier(); // is it a pointer, integer, array or struct? if(expr_type.id()==ID_pointer || expr_type.id()==ID_signedbv || expr_type.id()==ID_unsignedbv || expr_type.id()==ID_struct || expr_type.id()==ID_union || expr_type.id()==ID_array) { // look it up valuest::const_iterator v_it= values.find(id2string(identifier)+suffix); // try first component name as suffix if not yet found if(v_it==values.end() && (expr_type.id()==ID_struct || expr_type.id()==ID_union)) { const struct_union_typet &struct_union_type= to_struct_union_type(expr_type); const std::string first_component_name= struct_union_type.components().front().get_string(ID_name); v_it=values.find( id2string(identifier)+"."+first_component_name+suffix); } // not found? try without suffix if(v_it==values.end()) v_it=values.find(identifier); if(v_it!=values.end()) make_union(dest, v_it->second.object_map); else insert(dest, exprt(ID_unknown, original_type)); } else insert(dest, exprt(ID_unknown, original_type)); } else if(expr.id()==ID_if) { if(expr.operands().size()!=3) throw "if takes three operands"; get_value_set_rec(expr.op1(), dest, suffix, original_type, ns); get_value_set_rec(expr.op2(), dest, suffix, original_type, ns); } else if(expr.id()==ID_address_of) { if(expr.operands().size()!=1) throw expr.id_string()+" expected to have one operand"; get_reference_set(expr.op0(), dest, ns); } else if(expr.id()==ID_dereference) { object_mapt reference_set; get_reference_set(expr, reference_set, ns); const object_map_dt &object_map=reference_set.read(); if(object_map.begin()==object_map.end()) insert(dest, exprt(ID_unknown, original_type)); else { for(object_map_dt::const_iterator it1=object_map.begin(); it1!=object_map.end(); it1++) { const exprt &object=object_numbering[it1->first]; get_value_set_rec(object, dest, suffix, original_type, ns); } } } else if(expr.id()=="reference_to") { // old stuff, will go away object_mapt reference_set; get_reference_set(expr, reference_set, ns); const object_map_dt &object_map=reference_set.read(); if(object_map.begin()==object_map.end()) insert(dest, exprt(ID_unknown, original_type)); else { for(object_map_dt::const_iterator it=object_map.begin(); it!=object_map.end(); it++) { const exprt &object=object_numbering[it->first]; get_value_set_rec(object, dest, suffix, original_type, ns); } } } else if(expr.is_constant()) { // check if NULL if(expr.get(ID_value)==ID_NULL && expr_type.id()==ID_pointer) { insert(dest, exprt("NULL-object", expr_type.subtype()), 0); } else if(expr_type.id()==ID_unsignedbv || expr_type.id()==ID_signedbv) { // an integer constant got turned into a pointer insert(dest, exprt(ID_integer_address, unsigned_char_type())); } else insert(dest, exprt(ID_unknown, original_type)); } else if(expr.id()==ID_typecast) { if(expr.operands().size()!=1) throw "typecast takes one operand"; // let's see what gets converted to what const typet &op_type=ns.follow(expr.op0().type()); if(op_type.id()==ID_pointer) { // pointer-to-pointer -- we just ignore these get_value_set_rec(expr.op0(), dest, suffix, original_type, ns); } else if(op_type.id()==ID_unsignedbv || op_type.id()==ID_signedbv) { // integer-to-pointer if(expr.op0().is_zero()) insert(dest, exprt("NULL-object", expr_type.subtype()), 0); else { // see if we have something for the integer object_mapt tmp; get_value_set_rec(expr.op0(), tmp, suffix, original_type, ns); if(tmp.read().size()==0) { // if not, throw in integer insert(dest, exprt(ID_integer_address, unsigned_char_type())); } else if(tmp.read().size()==1 && object_numbering[tmp.read().begin()->first].id()==ID_unknown) { // if not, throw in integer insert(dest, exprt(ID_integer_address, unsigned_char_type())); } else { // use as is dest.write().insert(tmp.read().begin(), tmp.read().end()); } } } else insert(dest, exprt(ID_unknown, original_type)); } else if(expr.id()==ID_plus || expr.id()==ID_minus) { if(expr.operands().size()<2) throw expr.id_string()+" expected to have at least two operands"; object_mapt pointer_expr_set; mp_integer i; bool i_is_set=false; // special case for pointer+integer if(expr.operands().size()==2 && expr_type.id()==ID_pointer) { exprt ptr_operand; if(expr.op0().type().id()!=ID_pointer && expr.op0().is_constant()) { i_is_set=!to_integer(expr.op0(), i); ptr_operand=expr.op1(); } else { i_is_set=!to_integer(expr.op1(), i); ptr_operand=expr.op0(); } if(i_is_set) { i*=pointer_offset_size(ptr_operand.type().subtype(), ns); if(expr.id()==ID_minus) i.negate(); } get_value_set_rec( ptr_operand, pointer_expr_set, "", ptr_operand.type(), ns); } else { // we get the points-to for all operands, even integers forall_operands(it, expr) { get_value_set_rec( *it, pointer_expr_set, "", it->type(), ns); } } for(object_map_dt::const_iterator it=pointer_expr_set.read().begin(); it!=pointer_expr_set.read().end(); it++) { objectt object=it->second; // adjust by offset if(object.offset_is_zero() && i_is_set) object.offset=i; else object.offset_is_set=false; insert(dest, it->first, object); } }
void c_typecheck_baset::clean_type( const irep_idt &base_symbol_identifier, typet &type, std::list<codet> &code) { if(type.id()==ID_symbol) { // we need to follow for structs and such, but only once irep_idt identifier=to_symbol_type(type).get_identifier(); if(already_cleaned.insert(identifier).second) { symbol_tablet::symbolst::iterator s_it=symbol_table.symbols.find(identifier); assert(s_it!=symbol_table.symbols.end()); clean_type(identifier, s_it->second.type, code); } } else if(type.id()==ID_array) { array_typet &array_type=to_array_type(type); clean_type(base_symbol_identifier, array_type.subtype(), code); // The size need not be a constant! // This was simplified already by typecheck_array_type. exprt &size=array_type.size(); if(size.is_not_nil() && !size.is_constant() && size.id()!=ID_infinity && !(size.id()==ID_symbol && size.type().get_bool(ID_C_constant))) { // The criterion above can be tricked: // Of course we can modify a 'const' symbol, e.g., // using a pointer type cast. Interestingly, // at least gcc 4.2.1 makes the very same mistake! assert(current_symbol_id!=irep_idt()); const symbolt &base_symbol= lookup( base_symbol_identifier!=irep_idt()? base_symbol_identifier: current_symbol_id); // Need to pull out! We insert new symbol. locationt location=size.find_location(); unsigned count=0; irep_idt temp_identifier; std::string suffix; do { suffix="$array_size"+i2string(count); temp_identifier=id2string(base_symbol.name)+suffix; count++; } while(symbol_table.symbols.find(temp_identifier)!=symbol_table.symbols.end()); // add the symbol to symbol table symbolt new_symbol; new_symbol.name=temp_identifier; new_symbol.pretty_name=id2string(base_symbol.pretty_name)+suffix; new_symbol.base_name=id2string(base_symbol.base_name)+suffix; new_symbol.type=size.type(); new_symbol.type.set(ID_C_constant, true); new_symbol.is_file_local=true; new_symbol.is_type=false; new_symbol.is_thread_local=true; new_symbol.is_static_lifetime=false; new_symbol.value.make_nil(); new_symbol.location=location; symbol_table.add(new_symbol); // produce the code that declares and initializes the symbol symbol_exprt symbol_expr; symbol_expr.set_identifier(temp_identifier); symbol_expr.type()=new_symbol.type; code_declt declaration(symbol_expr); declaration.location()=location; code_assignt assignment; assignment.lhs()=symbol_expr; assignment.rhs()=size; assignment.location()=location; // store the code code.push_back(declaration); code.push_back(assignment); // fix type size=symbol_expr; } } else if(type.id()==ID_struct || type.id()==ID_union) { struct_union_typet::componentst &components= to_struct_union_type(type).components(); for(struct_union_typet::componentst::iterator it=components.begin(); it!=components.end(); it++) clean_type(base_symbol_identifier, it->type(), code); } else if(type.id()==ID_code) { // done, can't contain arrays } else if(type.id()==ID_pointer) { clean_type(base_symbol_identifier, type.subtype(), code); } else if(type.id()==ID_vector) { // should be clean } }
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+="|"; }
mp_integer alignment(const typet &type, const namespacet &ns) { // is the alignment given? const exprt &given_alignment= static_cast<const exprt &>(type.find(ID_C_alignment)); if(given_alignment.is_not_nil()) { mp_integer a_int; if(!to_integer(given_alignment, a_int)) return a_int; // we trust it blindly, no matter how nonsensical } // compute default if(type.id()==ID_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(); mp_integer 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 || type.id()==ID_c_bool) { unsigned width=to_bitvector_type(type).get_width(); return width%8?width/8+1:width/8; } else if(type.id()==ID_c_enum) { return alignment(type.subtype(), ns); } else if(type.id()==ID_c_enum_tag) { return alignment(ns.follow_tag(to_c_enum_tag_type(type)), ns); } 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; }
void c_typecheck_baset::typecheck_compound_type(struct_union_typet &type) { // These get replaced by symbol types later. irep_idt identifier; bool have_body=type.find(ID_components).is_not_nil(); if(type.find(ID_tag).is_nil()) { // Anonymous? Must come with body. assert(have_body); // produce symbol symbolt compound_symbol; compound_symbol.is_type=true; compound_symbol.type=type; compound_symbol.location=type.source_location(); typecheck_compound_body(to_struct_union_type(compound_symbol.type)); std::string typestr=type2name(compound_symbol.type); compound_symbol.base_name="#anon-"+typestr; compound_symbol.name="tag-#anon#"+typestr; identifier=compound_symbol.name; // We might already have the same anonymous union/struct, // and this is simply ok. Note that the C standard treats // these as different types. if(symbol_table.symbols.find(identifier)==symbol_table.symbols.end()) { symbolt *new_symbol; move_symbol(compound_symbol, new_symbol); } } else { identifier=type.find(ID_tag).get(ID_identifier); // does it exist already? symbol_tablet::symbolst::iterator s_it= symbol_table.symbols.find(identifier); if(s_it==symbol_table.symbols.end()) { // no, add new symbol irep_idt base_name=type.find(ID_tag).get(ID_C_base_name); type.remove(ID_tag); type.set(ID_tag, base_name); symbolt compound_symbol; compound_symbol.is_type=true; compound_symbol.name=identifier; compound_symbol.base_name=base_name; compound_symbol.type=type; compound_symbol.location=type.source_location(); compound_symbol.pretty_name=id2string(type.id())+" "+id2string(base_name); typet new_type=compound_symbol.type; if(compound_symbol.type.id()==ID_struct) compound_symbol.type.id(ID_incomplete_struct); else if(compound_symbol.type.id()==ID_union) compound_symbol.type.id(ID_incomplete_union); else assert(false); symbolt *new_symbol; move_symbol(compound_symbol, new_symbol); if(have_body) { typecheck_compound_body(to_struct_union_type(new_type)); new_symbol->type.swap(new_type); } } else { // yes, it exists already if(s_it->second.type.id()==ID_incomplete_struct || s_it->second.type.id()==ID_incomplete_union) { // Maybe we got a body now. if(have_body) { irep_idt base_name=type.find(ID_tag).get(ID_C_base_name); type.remove(ID_tag); type.set(ID_tag, base_name); typecheck_compound_body(type); s_it->second.type.swap(type); } } else if(have_body) { error().source_location=type.source_location(); error() << "redefinition of body of `" << s_it->second.pretty_name << "'" << eom; throw 0; } } } symbol_typet symbol_type; symbol_type.add_source_location()=type.source_location(); symbol_type.set_identifier(identifier); c_qualifierst original_qualifiers(type); type.swap(symbol_type); original_qualifiers.write(type); }
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; }