'Remove those return_from_call edges that actually do not return due to
calling some not-returning functions.
:return: None'

def _remove_non_return_edges(self):

    for func in self.kb.functions.values():
        graph = func.transition_graph
        all_return_edges = [(u, v) for (u, v, data) in graph.edges(data=True) if (data['type'] == 'return_from_call')]
        for return_from_call_edge in all_return_edges:
            (callsite_block_addr, return_to_addr) = return_from_call_edge
            call_func_addr = func.get_call_target(callsite_block_addr)
            if (call_func_addr is None):
                continue
            call_func = self.kb.functions.function(call_func_addr)
            if (call_func is None):
                continue
            if (call_func.returning is False):
                graph.remove_edge(call_func_addr, return_to_addr)
                nodes = self.get_all_nodes(callsite_block_addr)
                for n in nodes:
                    successors = self.get_successors_and_jumpkind(n, excluding_fakeret=False)
                    for (successor, jumpkind) in successors:
                        if ((jumpkind == 'Ijk_FakeRet') and (successor.addr == return_to_addr)):
                            self.remove_edge(n, successor)
