docs: def _scan_irsb(self, cfg_job, current_func_addr):
          """
          Generate a list of successors (generating them each as entries) to IRSB.
          Updates previous CFG nodes with edges.
  
          :param CFGJob cfg_job: The CFGJob instance.
          :param int current_func_addr: Address of the current function
          :return: a list of successors
          :rtype: list
          """
          addr, function_addr, cfg_node, irsb = self._generate_cfgnode(cfg_job, current_func_addr)
  
          # Add edges going to this node in function graphs
          cfg_job.apply_function_edges(self, clear=True)
  
          # function_addr and current_function_addr can be different. e.g. when tracing an optimized tail-call that jumps
          # into another function that has been identified before.
  
          if cfg_node is None:
              # exceptions occurred, or we cannot get a CFGNode for other reasons
              return [ ]
  
          self._graph_add_edge(cfg_node, cfg_job.src_node, cfg_job.jumpkind, cfg_job.src_ins_addr,
                               cfg_job.src_stmt_idx
                               )
          self._function_add_node(cfg_node, function_addr)
  
          if self.functions.get_by_addr(function_addr).returning is not True:
              self._updated_nonreturning_functions.add(function_addr)
  
          # If we have traced it before, don't trace it anymore
          real_addr = get_real_address_if_arm(self.project.arch, addr)
          if real_addr in self._traced_addresses:
              # the address has been traced before
              return [ ]
          else:
              # Mark the address as traced
              self._traced_addresses.add(real_addr)
  
          # irsb cannot be None here
          # assert irsb is not None
  
          # IRSB is only used once per CFGNode. We should be able to clean up the CFGNode here in order to save memory
          cfg_node.irsb = None
  
          self._process_block_arch_specific(addr, irsb, function_addr)
  
          # Scan the basic block to collect data references
          if self._collect_data_ref:
              self._collect_data_references(irsb, addr)
  
          # Get all possible successors
          irsb_next, jumpkind = irsb.next, irsb.jumpkind
          successors = [ ]
  
          last_ins_addr = None
          ins_addr = addr
          if irsb.statements:
              for i, stmt in enumerate(irsb.statements):
                  if isinstance(stmt, pyvex.IRStmt.Exit):
                      successors.append((i,
                                         last_ins_addr if self.project.arch.branch_delay_slot else ins_addr,
                                         stmt.dst,
                                         stmt.jumpkind
                                         )
                                        )
                  elif isinstance(stmt, pyvex.IRStmt.IMark):
                      last_ins_addr = ins_addr
                      ins_addr = stmt.addr + stmt.delta
          else:
              for ins_addr, stmt_idx, exit_stmt in irsb.exit_statements:
                  successors.append((
                      stmt_idx,
                      last_ins_addr if self.project.arch.branch_delay_slot else ins_addr,
                      exit_stmt.dst,
                      exit_stmt.jumpkind
                  ))
  
          successors.append((DEFAULT_STATEMENT,
                             last_ins_addr if self.project.arch.branch_delay_slot else ins_addr, irsb_next, jumpkind)
                            )
  
          entries = [ ]
  
          successors = self._post_process_successors(addr, irsb.size, successors)
  
          # Process each successor
          for suc in successors:
              stmt_idx, ins_addr, target, jumpkind = suc
  
              entries += self._create_jobs(target, jumpkind, function_addr, irsb, addr, cfg_node, ins_addr,
                                           stmt_idx
                                           )
  
          return entries