private static boolean removeEmptyBlock()

in src/org/jetbrains/java/decompiler/modules/code/DeadCodeHelper.java [66:186]


  private static boolean removeEmptyBlock(ControlFlowGraph graph, BasicBlock block, boolean merging) {
    boolean deletedRanges = false;

    if (block.getSeq().isEmpty()) {
      if (block.getSuccessors().size() > 1) {
        if (block.getPredecessors().size() > 1) {
          // ambiguous block
          throw new RuntimeException("ERROR: empty block with multiple predecessors and successors found");
        }
        else if (!merging) {
          throw new RuntimeException("ERROR: empty block with multiple successors found");
        }
      }

      Set<BasicBlock> setExits = new HashSet<>(graph.getLast().getPredecessors());

      if (block.getPredecessorExceptions().isEmpty() &&
          (!setExits.contains(block) || block.getPredecessors().size() == 1)) {

        if (setExits.contains(block)) {
          BasicBlock predecessor = block.getPredecessors().get(0);

          // FIXME: flag in the basic block
          if (predecessor.getSuccessors().size() != 1 ||
              (!predecessor.getSeq().isEmpty() &&
               predecessor.getSeq().getLastInstr().group == CodeConstants.GROUP_SWITCH)) {
            return false;
          }
        }

        Set<BasicBlock> predecessors = new HashSet<>(block.getPredecessors());
        Set<BasicBlock> successors = new HashSet<>(block.getSuccessors());

        // collecting common exception ranges of predecessors and successors
        Set<BasicBlock> setCommonExceptionHandlers = null;
        for (int i = 0; i < 2; ++i) {
          for (BasicBlock adjacent : i == 0 ? predecessors : successors) {
            if (setCommonExceptionHandlers == null) {
              setCommonExceptionHandlers = new HashSet<>(adjacent.getSuccessorExceptions());
            }
            else {
              setCommonExceptionHandlers.retainAll(adjacent.getSuccessorExceptions());
            }
          }
        }

        // check the block to be in each of the common ranges
        if (setCommonExceptionHandlers != null && !setCommonExceptionHandlers.isEmpty()) {
          for (BasicBlock handler : setCommonExceptionHandlers) {
            if (!block.getSuccessorExceptions().contains(handler)) {
              return false;
            }
          }
        }

        // remove ranges consisting of this one block
        List<ExceptionRangeCFG> lstRanges = graph.getExceptions();
        for (int i = lstRanges.size() - 1; i >= 0; i--) {
          ExceptionRangeCFG range = lstRanges.get(i);
          List<BasicBlock> lst = range.getProtectedRange();

          if (lst.size() == 1 && lst.get(0) == block) {
            if (DecompilerContext.getOption(IFernflowerPreferences.REMOVE_EMPTY_RANGES)) {
              block.removeSuccessorException(range.getHandler());
              lstRanges.remove(i);

              deletedRanges = true;
            }
            else {
              return false;
            }
          }
        }

        // connect remaining nodes
        if (merging) {
          BasicBlock predecessor = block.getPredecessors().get(0);
          predecessor.removeSuccessor(block);

          List<BasicBlock> successorList = new ArrayList<>(block.getSuccessors());
          for (BasicBlock successor : successorList) {
            block.removeSuccessor(successor);
            predecessor.addSuccessor(successor);
          }
        }
        else {
          for (BasicBlock predecessor : predecessors) {
            for (BasicBlock successor : successors) {
              predecessor.replaceSuccessor(block, successor);
            }
          }
        }

        // finally exit edges
        Set<BasicBlock> setFinallyExits = graph.getFinallyExits();
        if (setFinallyExits.contains(block)) {
          setFinallyExits.remove(block);
          setFinallyExits.add(predecessors.iterator().next());
        }

        // replace first if necessary
        if (graph.getFirst() == block) {
          if (successors.size() != 1) {
            throw new RuntimeException("multiple or no entry blocks!");
          }
          else {
            graph.setFirst(successors.iterator().next());
          }
        }

        // remove this block
        graph.removeBlock(block);

        if (deletedRanges) {
          removeDeadBlocks(graph);
        }
      }
    }

    return deletedRanges;
  }