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(); }
exprt ssa_alias_guard( const exprt &e1, const exprt &e2, const namespacet &ns) { exprt a1=address_canonizer(address_of_exprt(e1), ns); exprt a2=address_canonizer(address_of_exprt(e2), ns); // in some cases, we can use plain address equality, // as we assume well-aligned-ness mp_integer size1=pointer_offset_size(e1.type(), ns); mp_integer size2=pointer_offset_size(e2.type(), ns); if(size1>=size2) { exprt lhs=a1; exprt rhs=a2; if(ns.follow(rhs.type())!=ns.follow(lhs.type())) rhs=typecast_exprt(rhs, lhs.type()); return equal_exprt(lhs, rhs); } return same_object(a1, a2); }
exprt ssa_alias_guard( const exprt &e1, const exprt &e2, const namespacet &ns) { exprt a1=address_canonizer(address_of_exprt(e1), ns); // TODO: We should compare 'base' pointers here because // we have a higher chance that there was no pointer arithmetic // on the base pointer than that the result of the pointer // arithmetic points to a base pointer. // The following hack does that: if(a1.id()==ID_plus) a1=a1.op0(); exprt a2=address_canonizer(address_of_exprt(e2), ns); // in some cases, we can use plain address equality, // as we assume well-aligned-ness mp_integer size1=pointer_offset_size(e1.type(), ns); mp_integer size2=pointer_offset_size(e2.type(), ns); if(size1>=size2) { exprt lhs=a1; exprt rhs=a2; if(ns.follow(rhs.type())!=ns.follow(lhs.type())) rhs=typecast_exprt(rhs, lhs.type()); return equal_exprt(lhs, rhs); } return same_object(a1, a2); }
std::string array_name( const namespacet &ns, const exprt &expr) { if(expr.id()==ID_index) { if(expr.operands().size()!=2) throw "index takes two operands"; return array_name(ns, expr.op0())+"[]"; } else if(is_ssa_expr(expr)) { const symbolt &symbol= ns.lookup(to_ssa_expr(expr).get_object_name()); return "array `"+id2string(symbol.base_name)+"'"; } else if(expr.id()==ID_symbol) { const symbolt &symbol=ns.lookup(expr); return "array `"+id2string(symbol.base_name)+"'"; } else if(expr.id()==ID_string_constant) { return "string constant"; } else if(expr.id()==ID_member) { assert(expr.operands().size()==1); return array_name(ns, expr.op0())+"."+ expr.get_string(ID_component_name); } return "array"; }
bool type_eq(const typet &type1, const typet &type2, const namespacet &ns) { if(type1 == type2) return true; if(type1.id() == "symbol") { const symbolt &symbol = ns.lookup(type1); if(!symbol.is_type) throw "symbol " + id2string(symbol.name) + " is not a type"; return type_eq(symbol.type, type2, ns); } if(type2.id() == "symbol") { const symbolt &symbol = ns.lookup(type2); if(!symbol.is_type) throw "symbol " + id2string(symbol.name) + " is not a type"; return type_eq(type1, symbol.type, ns); } return false; }
void show_symbol_table_plain(const namespacet &ns, std::ostream &out) { out << std::endl << "Symbols:" << std::endl; out << "Number of symbols: " << ns.get_context().size() << std::endl; out << std::endl; ns.get_context().foreach_operand_in_order([&out, &ns](const symbolt &s) { int mode; if(s.mode == "") mode = 0; else { mode = get_mode(id2string(s.mode)); if(mode < 0) throw "symbol " + id2string(s.name) + " has unknown mode"; } std::unique_ptr<languaget> p(mode_table[mode].new_language()); std::string type_str, value_str; if(s.type.is_not_nil()) p->from_type(s.type, type_str, ns); if(s.value.is_not_nil()) p->from_expr(s.value, value_str, ns); out << "Symbol......: " << s.name << std::endl; out << "Pretty name.: " << s.pretty_name << std::endl; out << "Module......: " << s.module << std::endl; out << "Base name...: " << s.base_name << std::endl; out << "Mode........: " << s.mode << " (" << mode << ")" << std::endl; out << "Type........: " << type_str << std::endl; out << "Value.......: " << value_str << std::endl; out << "Flags.......:"; if(s.lvalue) out << " lvalue"; if(s.static_lifetime) out << " static_lifetime"; if(s.file_local) out << " file_local"; if(s.is_type) out << " type"; if(s.is_extern) out << " extern"; if(s.is_macro) out << " macro"; if(s.is_used) out << " used"; out << std::endl; out << "Location....: " << s.location << std::endl; out << std::endl; }); }
/// automated variable renaming /// \par parameters: symbol to be renamed, namespace /// \return new symbol void get_new_name(irep_idt &new_name, const namespacet &ns) { const symbolt *symbol; if(ns.lookup(new_name, symbol)) return; std::string prefix=id2string(new_name)+"_"; new_name=prefix+std::to_string(ns.get_max(prefix)+1); }
mp_integer compute_pointer_offset( const namespacet &ns, const exprt &expr) { if(expr.id()==ID_symbol) return 0; else if(expr.id()==ID_index) { assert(expr.operands().size()==2); const typet &array_type=ns.follow(expr.op0().type()); assert(array_type.id()==ID_array); mp_integer o=compute_pointer_offset(ns, expr.op0()); if(o!=-1) { mp_integer sub_size= pointer_offset_size(ns, array_type.subtype()); mp_integer i; if(sub_size!=0 && !to_integer(expr.op1(), i)) return o+i*sub_size; } // don't know } 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); mp_integer o=compute_pointer_offset(ns, expr.op0()); if(o!=-1) { if(type.id()==ID_union) return o; return o+member_offset( ns, to_struct_type(type), expr.get(ID_component_name)); } } else if(expr.id()==ID_string_constant) return 0; return -1; // don't know }
exprt get_failed_symbol( const symbol_exprt &expr, const namespacet &ns) { const symbolt &symbol=ns.lookup(expr); irep_idt failed_symbol_id=symbol.type.get("#failed_symbol"); if(failed_symbol_id==irep_idt()) return nil_exprt(); const symbolt &failed_symbol=ns.lookup(failed_symbol_id); return symbol_exprt(failed_symbol_id, failed_symbol.type); }
void remove_function_pointerst::fix_return_type( code_function_callt &function_call, goto_programt &dest) { // are we returning anything at all? if(function_call.lhs().is_nil()) return; const code_typet &code_type= to_code_type(ns.follow(function_call.function().type())); // type already ok? if(type_eq( function_call.lhs().type(), code_type.return_type(), ns)) return; symbolt &tmp_symbol=new_tmp_symbol(); tmp_symbol.type=code_type.return_type(); tmp_symbol.location=function_call.location(); symbol_exprt tmp_symbol_expr; tmp_symbol_expr.type()=tmp_symbol.type; tmp_symbol_expr.set_identifier(tmp_symbol.name); exprt old_lhs=function_call.lhs(); function_call.lhs()=tmp_symbol_expr; goto_programt::targett t_assign=dest.add_instruction(); t_assign->make_assignment(); t_assign->code=code_assignt( old_lhs, typecast_exprt(tmp_symbol_expr, old_lhs.type())); }
bool cpp_typecheck( exprt &expr, message_handlert &message_handler, const namespacet &ns) { contextt context; cpp_parse_treet cpp_parse_tree; cpp_typecheckt cpp_typecheck( cpp_parse_tree, context, ns.get_context(), "", message_handler); try { cpp_typecheck.typecheck_expr(expr); } catch(int e) { cpp_typecheck.error(); } catch(const char *e) { cpp_typecheck.error(e); } catch(const std::string &e) { cpp_typecheck.error(e); } return cpp_typecheck.get_error_found(); }
std::unique_ptr<languaget> get_language( const namespacet &ns, const irep_idt &identifier) { if(identifier=="") return std::unique_ptr<languaget>(get_default_language()); else { const symbolt *symbol; if(ns.lookup(identifier, symbol)) return std::unique_ptr<languaget>(get_default_language()); else if(symbol->mode=="") return std::unique_ptr<languaget>(get_default_language()); else { languaget *ptr=get_language_from_mode(symbol->mode); if(ptr==NULL) throw "symbol `"+id2string(symbol->name)+ "' has unknown mode '"+id2string(symbol->mode)+"'"; return std::unique_ptr<languaget>(ptr); } } }
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; }
bool ansi_c_typecheck( exprt &expr, message_handlert &message_handler, const namespacet &ns) { symbol_tablet symbol_table; ansi_c_parse_treet ansi_c_parse_tree; ansi_c_typecheckt ansi_c_typecheck( ansi_c_parse_tree, symbol_table, ns.get_symbol_table(), "", message_handler); try { ansi_c_typecheck.typecheck_expr(expr); } catch(int) { ansi_c_typecheck.error(); } catch(const char *e) { ansi_c_typecheck.error() << e << messaget::eom; } catch(const std::string &e) { ansi_c_typecheck.error() << e << messaget::eom; } return ansi_c_typecheck.get_error_found(); }
exprt remove_virtual_functionst::build_class_identifier( const exprt &src) { // the class identifier is in the root class exprt e=src; while(1) { const typet &type=ns.follow(e.type()); assert(type.id()==ID_struct); const struct_typet &struct_type=to_struct_type(type); const struct_typet::componentst &components=struct_type.components(); assert(!components.empty()); member_exprt member_expr( e, components.front().get_name(), components.front().type()); if(components.front().get_name()=="@class_identifier") { // found it return member_expr; } else { e=member_expr; } } }
void uninitialized_domaint::transform( locationt from, locationt to, ai_baset &ai, const namespacet &ns) { if(has_values.is_false()) return; switch(from->type) { case DECL: { const irep_idt &identifier= to_code_decl(from->code).get_identifier(); const symbolt &symbol=ns.lookup(identifier); if(!symbol.is_static_lifetime) uninitialized.insert(identifier); } break; default: { std::list<exprt> read=expressions_read(*from); std::list<exprt> written=expressions_written(*from); forall_expr_list(it, written) assign(*it); // we only care about the *first* uninitalized use forall_expr_list(it, read) assign(*it); } } }
std::string counterexample_value_binary( const exprt &expr, const namespacet &ns) { const typet &type=ns.follow(expr.type()); if(expr.id()==ID_constant) { if(type.id()==ID_unsignedbv || type.id()==ID_signedbv || type.id()==ID_bv || type.id()==ID_fixedbv || type.id()==ID_floatbv || type.id()==ID_pointer) { return expr.get_string(ID_value); } else if(type.id()==ID_bool) { return expr.is_true()?"1":"0"; } } else if(expr.id()==ID_array) { std::string result; forall_operands(it, expr) { if(result=="") result="{ "; else result+=", "; result+=counterexample_value_binary(*it, ns); } return result+" }"; }
code_function_callt get_destructor( const namespacet &ns, const typet &type) { if(type.id()==ID_symbol) { return get_destructor(ns, ns.follow(type)); } else if(type.id()==ID_struct) { const struct_typet &struct_type=to_struct_type(type); const struct_typet::componentst &components= struct_type.components(); for(struct_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) { if(it->type().id()==ID_code) { const code_typet &code_type=to_code_type(it->type()); if(code_type.return_type().id()==ID_destructor && code_type.parameters().size()==1) { const typet &arg_type=code_type.parameters().front().type(); if(arg_type.id()==ID_pointer && ns.follow(arg_type.subtype())==type) { exprt symbol_expr(ID_symbol, it->type()); symbol_expr.set(ID_identifier, it->get(ID_name)); code_function_callt function_call; function_call.function()=symbol_expr; return function_call; } } } } } return static_cast<const code_function_callt &>(get_nil_irep()); }
void compute_address_taken_in_symbols( std::set<irep_idt> &address_taken) { const symbol_tablet &symbol_table=ns.get_symbol_table(); for(const auto &s : symbol_table.symbols) compute_address_taken_functions(s.second.value, address_taken); }
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); } }
unsigned safe_width(const exprt &e, const namespacet &ns) { const typet &type=ns.follow(e.type()); if(type.id()=="pointer" || type.id()=="reference") return config.ansi_c.pointer_width; return boolbv_widtht(ns)(type); }
void constant_propagator_domaint::assign_rec( valuest &values, const exprt &lhs, const exprt &rhs, const namespacet &ns) { const typet & lhs_type = ns.follow(lhs.type()); const typet & rhs_type = ns.follow(rhs.type()); #ifdef DEBUG std::cout << "assign: " << from_expr(ns, "", lhs) << " := " << from_type(ns, "", rhs_type) << '\n'; #endif if(lhs.id()==ID_symbol && rhs.id()==ID_if) { exprt cond=rhs.op0(); assert(cond.operands().size()==2); if(values.is_constant(cond.op0()) && values.is_constant(cond.op1())) { if(cond.op0().id()==ID_index) { exprt index=cond.op0(); exprt new_expr=concatenate_array_id(index.op0(), index.op1(), index.type()); values.replace_const(new_expr); cond.op0()=new_expr; cond = simplify_expr(cond,ns); } else assert(0); assign(values, to_symbol_expr(lhs), cond, ns); } } else if(lhs.id()==ID_symbol && rhs_type.id()!=ID_array && rhs_type.id()!=ID_struct && rhs_type.id()!=ID_union) { if(values.is_constant(rhs)) assign(values, to_symbol_expr(lhs), rhs, ns); else values.set_to_top(to_symbol_expr(lhs)); } else if(lhs.id()==ID_symbol && lhs_type.id()==ID_array && rhs_type.id()==ID_array) { exprt new_expr; mp_integer idx=0; forall_operands(it, rhs) { new_expr=concatenate_array_id(lhs, idx, it->type()); assign(values, to_symbol_expr(new_expr), *it, ns); idx = idx +1; }
void compute_address_taken_in_symbols( std::set<irep_idt> &address_taken) { const symbol_tablet &symbol_table=ns.get_symbol_table(); const symbol_tablet::symbolst &s=symbol_table.symbols; for(symbol_tablet::symbolst::const_iterator it=s.begin(); it!=s.end(); ++it) compute_address_taken_functions(it->second.value, address_taken); }
bool ansi_c_typecheck( exprt &expr, message_handlert &message_handler, const namespacet &ns) { contextt context1, context2; ansi_c_parse_treet ansi_c_parse_tree; context1 = ns.get_context(); #if 0 ansi_c_typecheckt ansi_c_typecheck( ansi_c_parse_tree, context, ns.get_context(), "", message_handler); #endif ansi_c_typecheckt ansi_c_typecheck( ansi_c_parse_tree, context1, context2, "", message_handler); try { ansi_c_typecheck.typecheck_expr(expr); } catch(int e) { ansi_c_typecheck.error(); } catch(const char *e) { ansi_c_typecheck.error(e); } catch(const std::string &e) { ansi_c_typecheck.error(e); } return ansi_c_typecheck.get_error_found(); }
exprt ssa_alias_value( const exprt &e1, const exprt &e2, const namespacet &ns) { const typet &e1_type=ns.follow(e1.type()); const typet &e2_type=ns.follow(e2.type()); // type matches? if(e1_type==e2_type) return e2; exprt a1=address_canonizer(address_of_exprt(e1), ns); exprt a2=address_canonizer(address_of_exprt(e2), ns); exprt offset1=pointer_offset(a1); // array index possible? if(e2_type.id()==ID_array && e1_type==ns.follow(e2_type.subtype())) { // this assumes well-alignedness mp_integer element_size=pointer_offset_size(e2_type.subtype(), ns); if(element_size==1) return index_exprt(e2, offset1, e1.type()); else if(element_size>1) { exprt index= div_exprt(offset1, from_integer(element_size, offset1.type())); return index_exprt(e2, index, e1.type()); } } byte_extract_exprt byte_extract(byte_extract_id(), e1.type()); byte_extract.op()=e2; byte_extract.offset()=offset1; return byte_extract; }
code_function_callt get_destructor( const namespacet &ns, const typet &type) { if(type.id()==ID_symbol) { return get_destructor(ns, ns.follow(type)); } else if(type.id()==ID_struct) { const exprt &methods=static_cast<const exprt&>(type.find(ID_methods)); forall_operands(it, methods) { if(it->type().id()==ID_code) { const code_typet &code_type=to_code_type(it->type()); if(code_type.return_type().id()==ID_destructor && code_type.parameters().size()==1) { const typet &arg_type=code_type.parameters().front().type(); if(arg_type.id()==ID_pointer && ns.follow(arg_type.subtype())==type) { exprt symbol_expr(ID_symbol, it->type()); symbol_expr.set(ID_identifier, it->get(ID_name)); code_function_callt function_call; function_call.function()=symbol_expr; return function_call; } } } } } return static_cast<const code_function_callt &>(get_nil_irep()); }
void get_symbols_rec( const namespacet &ns, const symbolt &symbol, find_symbols_sett &dest) { dest.insert(symbol.name); find_symbols_sett new_symbols; find_type_and_expr_symbols(symbol.type, new_symbols); find_type_and_expr_symbols(symbol.value, new_symbols); if(symbol.type.id()==ID_code) { const code_typet &code_type=to_code_type(symbol.type); const code_typet::parameterst ¶meters=code_type.parameters(); for(code_typet::parameterst::const_iterator it=parameters.begin(); it!=parameters.end(); it++) { irep_idt id=it->get_identifier(); const symbolt *s; // identifiers for prototypes need not exist if(!ns.lookup(id, s)) new_symbols.insert(id); } } for(find_symbols_sett::const_iterator it=new_symbols.begin(); it!=new_symbols.end(); it++) { if(dest.find(*it)==dest.end()) { dest.insert(*it); get_symbols_rec(ns, ns.lookup(*it), dest); // recursive call } } }
inline static unsigned bv_width( const typet &type, const namespacet &ns) { if(type.id()==ID_c_enum_tag) { const typet &t=ns.follow_tag(to_c_enum_tag_type(type)); assert(t.id()==ID_c_enum); return bv_width(t.subtype(), ns); } return unsafe_string2unsigned(type.get_string(ID_width)); }
exprt remove_virtual_functionst::get_method( const irep_idt &class_id, const irep_idt &component_name) const { irep_idt id=id2string(class_id)+"."+ id2string(component_name); const symbolt *symbol; if(ns.lookup(id, symbol)) return nil_exprt(); return symbol->symbol_expr(); }
bool value_sett::field_sensitive( const irep_idt &id, const typet &type, const namespacet &ns) { // we always track fields on these if(has_prefix(id2string(id), "value_set::dynamic_object") || id=="value_set::return_value" || id=="value_set::memory") return true; // otherwise it has to be a struct return ns.follow(type).id()==ID_struct; }