boolean (StructClass cl, StructMethod mt, RootStatement root, ControlFlowGraph graph) { int bytecodeVersion = mt.getBytecodeVersion(); LinkedList<Statement> stack = new LinkedList<>(); stack.add(root); while (!stack.isEmpty()) { Statement stat = stack.removeLast(); Statement parent = stat.getParent(); if (parent != null && parent.type == StatementType.CATCH_ALL && stat == parent.getFirst() && !parent.isCopied()) { CatchAllStatement fin = (CatchAllStatement)parent; BasicBlock head = fin.getBasichead().getBlock(); BasicBlock handler = fin.getHandler().getBasichead().getBlock(); if (catchallBlockIDs.containsKey(handler.id)) { // do nothing } else if (finallyBlockIDs.containsKey(handler.id)) { fin.setFinally(true); Integer var = finallyBlockIDs.get(handler.id); fin.setMonitor(var == null ? null : new VarExprent(var, VarType.VARTYPE_INT, varProcessor)); } else { Record inf = getFinallyInformation(cl, mt, root, fin); if (inf == null) { // inconsistent finally catchallBlockIDs.put(handler.id, null); } else { if (DecompilerContext.getOption(IFernflowerPreferences.FINALLY_DEINLINE) && verifyFinallyEx(graph, fin, inf)) { finallyBlockIDs.put(handler.id, null); } else { int varIndex = DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER); insertSemaphore(graph, getAllBasicBlocks(fin.getFirst()), head, handler, varIndex, inf, bytecodeVersion); finallyBlockIDs.put(handler.id, varIndex); } DeadCodeHelper.removeDeadBlocks(graph); // e.g. multiple return blocks after a nested finally DeadCodeHelper.removeEmptyBlocks(graph); DeadCodeHelper.mergeBasicBlocks(graph); } return true; } } stack.addAll(stat.getStats()); } return false; }