void remove_virtual_functionst::get_functions( const exprt &function, functionst &functions) { const irep_idt class_id=function.get(ID_C_class); const irep_idt component_name=function.get(ID_component_name); assert(!class_id.empty()); // iterate over all children, transitively std::vector<irep_idt> children= class_hierarchy.get_children_trans(class_id); for(const auto & child : children) { exprt method=get_method(child, component_name); if(method.is_not_nil()) { functiont function; function.class_id=child; function.symbol_expr=to_symbol_expr(method); function.symbol_expr.set(ID_C_class, child); functions.push_back(function); } } // Start from current class, go to parents until something // is found. irep_idt c=class_id; while(!c.empty()) { exprt method=get_method(c, component_name); if(method.is_not_nil()) { functiont function; function.class_id=c; function.symbol_expr=to_symbol_expr(method); function.symbol_expr.set(ID_C_class, c); functions.push_back(function); break; // abort } const class_hierarchyt::idst &parents= class_hierarchy.class_map[c].parents; if(parents.empty()) break; c=parents.front(); } }
void remove_virtual_functionst::get_functions( const exprt &function, functionst &functions) { const irep_idt class_id=function.get(ID_C_class); const irep_idt component_name=function.get(ID_component_name); assert(!class_id.empty()); functiont root_function; // Start from current class, go to parents until something // is found. irep_idt c=class_id; while(!c.empty()) { exprt method=get_method(c, component_name); if(method.is_not_nil()) { root_function.class_id=c; root_function.symbol_expr=to_symbol_expr(method); root_function.symbol_expr.set(ID_C_class, c); break; // abort } const class_hierarchyt::idst &parents= class_hierarchy.class_map[c].parents; if(parents.empty()) break; c=parents.front(); } if(root_function.class_id.empty()) { // No definition here; this is an abstract function. root_function.class_id=class_id; } // iterate over all children, transitively std::set<irep_idt> visited; get_child_functions_rec( class_id, root_function.symbol_expr, component_name, functions, visited); if(root_function.symbol_expr!=symbol_exprt()) functions.push_back(root_function); }
bool remove_const_function_pointerst::try_resolve_typecast_function_call( const typecast_exprt &typecast_expr, functionst &out_functions) { // We simply ignore typecasts and assume they are valid // I thought simplify_expr would deal with this, but for example // a cast from a 32 bit width int to a 64bit width int it doesn't seem // to allow functionst typecast_values; bool resolved= try_resolve_function_call(typecast_expr.op(), typecast_values); if(resolved) { out_functions.insert(typecast_values.begin(), typecast_values.end()); return true; } else { LOG("Failed to squash typecast", typecast_expr); return false; } }
bool remove_const_function_pointerst::try_resolve_function_calls( const expressionst &exprs, functionst &out_functions) { for(const exprt &value : exprs) { functionst potential_out_functions; bool resolved_value= try_resolve_function_call(value, potential_out_functions); if(resolved_value) { out_functions.insert( potential_out_functions.begin(), potential_out_functions.end()); } else { LOG("Could not resolve expression in array", value); return false; } } return true; }
/// Used by get_functions to track the most-derived parent that provides an /// override of a given function. /// \par parameters: `this_id`: class name /// `last_method_defn`: the most-derived parent of `this_id` to define the /// requested function /// `component_name`: name of the function searched for /// \return `functions` is assigned a list of {class name, function symbol} /// pairs indicating that if `this` is of the given class, then the call will /// target the given function. Thus if A <: B <: C and A and C provide /// overrides of `f` (but B does not), get_child_functions_rec("C", C.f, "f") /// -> [{"C", C.f}, {"B", C.f}, {"A", A.f}] void remove_virtual_functionst::get_child_functions_rec( const irep_idt &this_id, const symbol_exprt &last_method_defn, const irep_idt &component_name, functionst &functions, std::set<irep_idt> &visited) const { auto findit=class_hierarchy.class_map.find(this_id); if(findit==class_hierarchy.class_map.end()) return; for(const auto &child : findit->second.children) { if(!visited.insert(child).second) continue; exprt method=get_method(child, component_name); functiont function(child); if(method.is_not_nil()) { function.symbol_expr=to_symbol_expr(method); function.symbol_expr.set(ID_C_class, child); } else { function.symbol_expr=last_method_defn; } functions.push_back(function); get_child_functions_rec( child, function.symbol_expr, component_name, functions, visited); } }
bool remove_const_function_pointerst::try_resolve_function_call( const exprt &expr, functionst &out_functions) { assert(out_functions.empty()); const exprt &simplified_expr=simplify_expr(expr, ns); bool resolved=false; functionst resolved_functions; if(simplified_expr.id()==ID_index) { const index_exprt &index_expr=to_index_expr(simplified_expr); resolved=try_resolve_index_of_function_call(index_expr, resolved_functions); } else if(simplified_expr.id()==ID_member) { const member_exprt &member_expr=to_member_expr(simplified_expr); resolved=try_resolve_member_function_call(member_expr, resolved_functions); } else if(simplified_expr.id()==ID_address_of) { address_of_exprt address_expr=to_address_of_expr(simplified_expr); resolved=try_resolve_address_of_function_call( address_expr, resolved_functions); } else if(simplified_expr.id()==ID_dereference) { const dereference_exprt &deref=to_dereference_expr(simplified_expr); resolved=try_resolve_dereference_function_call(deref, resolved_functions); } else if(simplified_expr.id()==ID_typecast) { typecast_exprt typecast_expr=to_typecast_expr(simplified_expr); resolved= try_resolve_typecast_function_call(typecast_expr, resolved_functions); } else if(simplified_expr.id()==ID_symbol) { if(simplified_expr.type().id()==ID_code) { resolved_functions.insert(simplified_expr); resolved=true; } else { LOG("Non const symbol wasn't squashed", simplified_expr); resolved=false; } } else { LOG("Unrecognised expression", simplified_expr); resolved=false; } if(resolved) { out_functions.insert(resolved_functions.begin(), resolved_functions.end()); return true; } else { return false; } }