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); }
/// 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); } }